#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 , 5 years ago
Type: | Uncategorized → Bug |
---|
follow-up: 3 comment:2 by , 5 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
comment:3 by , 5 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.POST
dict. 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.POST
dict. But if you use any other content type, it's your duty to handle the request body and implement a custom content parsing.