1

I am testing an endpoint in the following manner:

from rest_framework.test import APIClient
from django.urls import reverse
import json


client = APIClient()
response = client.post(list_url, {'name': 'Zagyg Co'})

I find that the model object is being created with a name of [Zagyg Co] instead of Zagyg Co.

Inspecting the request object reveals the following:

self._request.META['CONTENT_TYPE']
#=> 'multipart/form-data; boundary=BoUnDaRyStRiNg; charset=utf-8'
self._request.body
#=> b'--BoUnDaRyStRiNg\r\nContent-Disposition: form-data; name="name"\r\n\r\nZagyg Co\r\n--BoUnDaRyStRiNg--\r\n'
self._request.POST
#=> <QueryDict: {'name': ['Zagyg Co']}> 

Using JSON like so:

response = client.post(
    list_url, 
    json.dumps({'name': 'Zagyg Co'}), 
    content_type='application/json',
)

sets the name correctly. Why is this so?

1 Answers1

0

request.data is a Django QueryDict. When the data is sent as a multipart form it handles potential multiple values of the same field by putting it in a list.

Using its dict method or using dictionary access syntax returns the last value stored in the relevant key(s):

request.data['name']
#=> 'Zagyg Co'
request.dict()
#=> {'name': 'Zagyg Co'}

Which is great if it's guaranteed that each key has a single value. For list values there's getlist:

request.data.getlist('name')
#=> ['Zagyg Co']

For mixes of keys with single and multiple values it seems like manual parsing is required.