Reputation: 41
I'm trying to send data from a service running with python through a http PATCH
request to another running Django with Django API Rest Framework using requests.
The SomeAccount
has a field appUserId
which is now -1
.
Here is the some_sender.py who knows about the app_user_id
(=77
, e.g.):
auth = ('someusrname', 'somepwd')
data = {"appUserId": app_user_id}
url = 'myapi:8000/someaccounts/1'
r = requests.patch(url, data=data, auth=auth)
print r.status_code
#> 200
When I check the value of the item at GET /someaccounts/1
it still has appUserId=-1
.
While debugging, in Django I get the request, but without any data - it's just an empty dict.
Here is how I it looks in Django:
mysite/myapp/urls.py:
from django.conf.urls import include, url
from rest_framework import routers
from . import views
router = routers.DefaultRouter()
router.register(r'someaccount', views.SomeAccountViewSet)
# ...
urlpatterns = [
url(r'^', include(router.urls)),
# ...
]
mysite/myapp/models.py:
from django.db import models
# ...
class SomeAccount(models.Model):
"""
Some account can include all the data related to some user's account.
"""
# ...
appUserId = models.BigIntegerField(blank=True, null=True)
mysite/myapp/views.py:
class SomeAccountViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows some accounts to be viewed or edited.
"""
queryset = SomeAccount.objects.all()
serializer_class = SomeAccountSerializer
mysite/myapp/serializers.py:
from models import SomeAccount
# ...
class SomeAccountSerializer(serializers.ModelSerializer):
id = serializers.ReadOnlyField()
class Meta:
model = SomeAccount
fields = ('url', 'id', 'appUserId')
depth = 3
partial = True
def update(self, someAccount, account_data):
if 'appUserId' in account_data:
someAccount.appUserId = account_data.pop('appUserId')
someAccount.save()
return someAccount
In SomeAccountSerializer
when debugging on the incoming request I get the following values:
account_data: {}
initial_data: <QueryDict: {}>
someAccount: {'appUserId': -1, 'id': 1}
I tried to send the same values through the Postman Google Chrome plugin and it worked.
I also tried to set the content-type
header:
with application/x-www-form-urlencoded
:
requests.patch(
url, data=data, auth=auth,
headers={'content-type': 'application/x-www-form-urlencoded'}
)
with application/form-data
:
requests.patch(
url, data=data, auth=auth,
headers={'content-type': 'application/form-data'}
)
with application/json
:
requests.patch(
url, json=json.dumps(data), auth=auth,
headers={'content-type': 'application/json'}
)
without being successful.
EDIT: python-requests is sending the request correctly. The problem probably lies in how Django is handling it.
Upvotes: 4
Views: 1189
Reputation: 1784
Just ran into this same issue. Was missing the trailing slash on the URL. When Django redirected to the URL with the trailing slash, it seemed to drop the payload of the PATCH.
Upvotes: 1
Reputation: 38
You should check your network traffic to make sure where the problem appears. If I use
import requests
app_user_id = 7
auth = ('someusrname', 'somepwd')
data = {'appUserId': app_user_id}
url = 'http://localhost:8000/someaccounts/1'
r = requests.put(url, data=data, auth=auth)
print r.status_code
and open a local socket with netcat (nc -l 8000) I am getting the data form encoded:
PUT /someaccounts/1 HTTP/1.1
Host: localhost:8000
Content-Length: 11
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: python-requests/2.8.1
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Authorization: Basic c29tZXVzcm5hbWU6c29tZXB3ZA==
appUserId=7
Upvotes: 0