Django Rest Framework: empty request.data

18,406

Solution 1

You need to send the payload as a serialized json object.

import json
import requests
payload = {"foo":"bar"}
headers = {'Content-type': 'application/json'}
r = requests.put("https://.../myPk/", data=json.dumps(payload), headers=headers)

Otherwise what happens is that DRF will actually complain about:

*** ParseError: JSON parse error - No JSON object could be decoded

You would see that error message by debugging the view (e.g. with pdb or ipdb) or printing the variable like this:

def update(self, request, pk = None):
    print pk
    print str(request.data)

Solution 2

Check 2 issues here:-

  1. Json format is proper or not.
  2. Url is correct or not(I was missing trailing backslash in my url because of which I was facing the issue)

Hope it helps

Solution 3

Assuming you're on a new enough version of requests you need to do:

import requests

payload = {"foo":"bar"}
r = requests.put("https://.../myPk", json=payload, headers=headers)

Then it will properly format the payload for you and provide the appropriate headers. Otherwise, you're sending application/x-www-urlformencoded data which DRF will not parse correctly since you tell it that you're sending JSON.

Share:
18,406
floatingpurr
Author by

floatingpurr

...where is my Dr. Pepper!?

Updated on June 11, 2022

Comments

  • floatingpurr
    floatingpurr almost 2 years

    I have the following code for a view of DRF:

    from rest_framework import viewsets
    
    class MyViewSet(viewsets.ViewSet):
    
        def update(self, request, pk = None):
            print pk
            print request.data
    

    I call the URL via python-requests in the following way:

    import requests
    payload = {"foo":"bar"}
    headers = {'Content-type': 'application/json'}
    r = requests.put("https://.../myPk", data= payload, headers=headers)
    

    but when the request is received from the server, request.data is empty. Here there is the output:

    myPk
    <QueryDict: {}>
    

    How can I fix this problem?

  • floatingpurr
    floatingpurr almost 9 years
    Ok, but I specify the format in headers = {'Content-type': 'application/json'}
  • floatingpurr
    floatingpurr almost 9 years
    I tried to serialize the dictionary as a json but it still not working. When I read the print of the var values I get always myPk and <QueryDict: {}>.
  • sthzg
    sthzg almost 9 years
    What output do you get when you do print request.stream.read() instead of print request.data (it's important to remove print request.data for that test). This should show you the unaltered raw data from your request. Do you see anything there? .stream in the docs
  • floatingpurr
    floatingpurr almost 9 years
    I added the line print request.stream.read() immediately after def update(self, request, pk = None):. The output is: AttributeError: 'NoneType' object has no attribute 'read'
  • floatingpurr
    floatingpurr almost 9 years
    Ok I solved! The issues was: (i) JSON serialization and (ii) trailing slash in the request URL. r = requests.put("https://.../myPk/", data=json.dumps(payload), headers=headers). sthzg, if you update the URL of yout above answer, adding a trailing slashi, I can flag it as accepted (Hoping it is a regular operation for stackexchange...)
  • sthzg
    sthzg almost 9 years
    Glad you solved it. I actually thought about the trailing slash and used it in the testing code, but forgot to test it for errors without it. Updated the path in the answer.