Difference between content_type=application/json and format=json in DRF APIClient

Viewed 328

I'm using rest_framework.test.APIClient for unit tests in my project. I used a dictionary as a request data, so None values there are not parsed properly as it doesn't understand the format. I added format="json" as a parameter to client.post() and it worked fine. However adding content_type="application/json" solved the problem as well and I want to know what's the difference.

1 Answers

The APIClient in rest framework extends from the test client in django app and adds extra functionalities using APIRequestFactory to deal with each type of request e.g. get, post etc. The django test client accepts content_type and the rest framework APIClient accepts both format and content_type. But, you can't set both at the same time in the APIClient as it will throw an error.

Let's look at both the scenarios:

  • Using content_type='application/json':

    In this case, the content_type is passed as it is to the django test client and there it uses json module to dump the data if the data is one of dict, list or tuple.

  • Using format=json:

    rest_framework has a setting TEST_REQUEST_RENDERER_CLASSES where it defines different renderers for different types of data.

    'TEST_REQUEST_RENDERER_CLASSES': [
        'rest_framework.renderers.MultiPartRenderer',
        'rest_framework.renderers.JSONRenderer'
    ],
    

    From these renderers, APIRequestFactory creates a mapping between the specified format as the key. When format='json' is sent in the request, it looks for the renderer and matches JSONRenderer. It then tries to encode the given data using this particular renderer. This renderer also specifies the media_type which equals to application/json and is set as content_type and both the encoded data and content_type are passed to django test client. Because now the encoded data is a string, even passing content_type won't dump the data twice.

Related