Reputation: 1607
I tried to POST a query in json in postman's raw body like below:
and I got 500 internal error server and HTML results like below
Otherwise, I'm able to POST using form-data and from a script ran from the terminal using the same json format.
I use Django 1.5.12 to serve the API and python 2.7.
Can anyone help?
Upvotes: 0
Views: 2486
Reputation: 10709
If you are using request.POST in your code to access the HTTP POST body values, then take note that as stated in https://www.django-rest-framework.org/tutorial/2-requests-and-responses/
request.POST # Only handles form data. Only works for 'POST' method.
If you would like your view to be able to read HTTP POST body values both from form-data (or x-www-form-urlencoded) and raw (JSON format) at the same time, then you cannot use request.POST alone. You could either:
urls.py
path('printpostedvalues/', printpostedvalues_view),
views.py
@csrf_exempt
def printpostedvalues_view(request):
print("request.body", request.body)
try:
print("json.loads(request.body)", json.loads(request.body))
for k, v in json.loads(request.body).items():
print("json.loads(request.body)", k, "-->", v)
except Exception:
print("request.body's string value is not in the format of JSON key:value pairs")
print("request.POST", request.POST)
for k, v in request.POST.items():
print("request.POST", k, "-->", v)
return HttpResponse("Printed values in console...")
Perform an HTTP POST http://127.0.0.1:8000/printpostedvalues/ using Postman.
HTTP Body
KEY - VALUE
athlete - LeBron James
status - GOAT!
quote - Strive for greatness
Console Output
request.GET <QueryDict: {}>
request.body b'----------------------------269460357877673035654590\r\nContent-Disposition: form-data; name="athlete"\r\n\r\nLeBron James\r\n----------------------------269460357877673035654590\r\nContent-Disposition: form-data; name="status"\r\n\r\nGOAT!\r\n----------------------------269460357877673035654590\r\nContent-Disposition: form-data; name="quote"\r\n\r\nStrive for greatness\r\n----------------------------269460357877673035654590--\r\n'
request.body's string value is not in the format of JSON key:value pairs
request.POST <QueryDict: {'athlete': ['LeBron James'], 'status': ['GOAT!'], 'quote': ['Strive for greatness']}>
request.POST athlete --> LeBron James
request.POST status --> GOAT!
request.POST quote --> Strive for greatness
[11/Mar/2020 04:57:43] "POST /printpostedvalues/ HTTP/1.1" 200 28
Conclusion:
The request.body contains the HTTP POST information from the form-data but is clearly not in the JSON format and thus cannot be parsed through json.loads(). The request.POST also contains the values.
HTTP Body
same as Case 1
Console Output
same as Case 1 except for line 2 -
request.body b'athlete=LeBron%20James&status=GOAT%21"e=Strive%20for%20greatness'
Conclusion:
same as Case 1
HTTP Body
{
"athlete" : "LeBron James",
"status" : "GOAT!",
"quote" : "Strive for greatness"
}
Console Output
request.GET <QueryDict: {}>
request.body b'{\n "athlete" : "LeBron James",\n "status" : "GOAT!",\n "quote" : "Strive for greatness"\n}'
json.loads(request.body) {'athlete': 'LeBron James', 'status': 'GOAT!', 'quote': 'Strive for greatness'}
json.loads(request.body) athlete --> LeBron James
json.loads(request.body) status --> GOAT!
json.loads(request.body) quote --> Strive for greatness
request.POST <QueryDict: {}>
Conclusion:
The request.body contains the HTTP POST information from the raw JSON data and is in the JSON format and thus possible to be parsed through json.loads(). The request.POST does not contain any values.
Long story short, do not rely on request.POST if you expect HTTP POST body values to come not just as form-data but also as raw JSON format. If you are using rest_framework for this, your best option is to use request.data because it will be able to catch all information coming from an HTTP POST regardless of format.
Upvotes: 0
Reputation: 1497
When you submit form data the content-type
header will be
Content-Type: multipart/form-data
and in your Django view, you will do something like below to read the posted data:
name = request.POST.get('name')
However, when you post data using the way you did now with the postman, the header will be:
Content-Type: application/json
and to grab this json data, you can do something like:
import json
mydata = json.loads(request.body)
name = mydata.get('name')
Status 500, must be because you have not handled the case for json request in your view.
Upvotes: 2