#30840 closed Bug (invalid)
Sending JSON using the django test client fails when providing content_type='application/json'
| Reported by: | Fernando Cordeiro | Owned by: | nobody |
|---|---|---|---|
| Component: | Testing framework | Version: | 2.2 |
| Severity: | Normal | Keywords: | ajax |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Given the following statement from the docs (https://docs.djangoproject.com/en/2.2/topics/testing/tools/#django.test.Client.post):
If you provide content_type as application/json, the data is serialized using json.dumps() if it’s a dict, list, or tuple.
I created the following TestCase in order to test if my AJAX POST request could update my model correctly:
class MyUpdateViewTest(TestCase):
def test_update_model_field(self):
self.client.force_login(self.user)
url = reverse('MyModel_update', args=[pk])
resp = self.client.post(
url,
data={'field' : 4},
content_type='application/json',
HTTP_X_REQUESTED_WITH='XMLHttpRequest'
)
obj = MyModel.objects.filter(...)
self.assertEqual(obj[0].field, 4)
The corresponding view:
class MyUpdateView(UpdateView):
"""Updates a MyModel via its pk with AJAX form data"""
model = MyModel
form_class = MyModelForm
def form_valid(self, form):
self.object = form.save()
data = {'pk': self.object.pk}
return JsonResponse(data)
def form_invalid(self, form):
return JsonResponse(form.errors, status=400)
def post(self, request, *args, **kwargs):
if request.is_ajax():
return super().post(self, request, *args, **kwargs)
else:
return HttpResponseBadRequest()
What happened was that whenever I added content_type='application/json', the view never received any data at all (i.e. request.POST was an empty queryset) which then made the form.is_valid() method fail and return a form field error. I tried this with and without ´json.dumps()` on the POST data.
However, as soon as I removed the content_type='application/json' parameter, the test worked! So, given the docs, I believe a bug is afoot.
This problem only happened during testing.
Change History (3)
comment:1 by , 6 years ago
| Type: | Uncategorized → Bug |
|---|
follow-up: 3 comment:2 by , 6 years ago
| Resolution: | → invalid |
|---|---|
| Status: | new → closed |
comment:3 by , 6 years ago
Replying to Claude Paroz:
That's expected behavior. A Django request knows how to handle
'multipart/form-data'or'application/x-www-form-urlencoded'to populate therequest.POSTdict. But if you use any other content type, it's your duty to handle the request body and implement a custom content parsing.
I'm sorry. Given what was stated in the aforementioned documentation and what the method django.client.test.RequestFactory._encode_json does, I was under the impression just using a 'application/json' content_type and having my data as a dict would be enough for Django to correctly parse its content during testing.
That's expected behavior. A Django request knows how to handle
'multipart/form-data'or'application/x-www-form-urlencoded'to populate therequest.POSTdict. But if you use any other content type, it's your duty to handle the request body and implement a custom content parsing.