I have a Django view which returns a list of objects, or allows you to create one if you POST...
@csrf_exempt
def quantities(request):
if request.method == "POST":
kwargs = {**request.POST}
print(request.POST)
quantity = Quantity.objects.create(**kwargs)
return JsonResponse({"quantity": f"/quantities/{quantity.id}/"})
return JsonResponse([], safe=False)
If it gets a GET request it returns a list of quantities (code not shown), which works fine, and if it gets a POST request it uses POST data to create a new quantity. (I'm aware DRF does all this for you, but for my first API I wanted to try doing it manually - you just understand it better that way.)
Anyway in my test, I use requests to check this works...
response = requests.post(
self.live_server_url + f"/quantities/", data={
"name": "Height", "units": "m", "description": "Human Height"
}
)
This doesn't work - it doesn't pass any data. That print
statement in the view above just prints <QueryDict: {}>
. For some reason the POST data that I put in the request has gone from the request by the time it passes through all the middleware and gets to the view.
The only thing I can think of is that the @csrf_exempt
decorator is removing POST data, though I can't imagine why. I've looked at its source code and it doesn't seem to be doing that, but I can't check because removing the decorator means the view just returns a 403 response.
Where is my POST data going?
So it turns out that for some reason the fact that my request had a header "Content-Type": "application/json"
was making Django not create a POST dictionary from the request body. I have no idea why but removing that header fixed the issue.