Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework: Nested Serializers with FileField/ImageField

I have a serializer that follows a model similar to:

class Ticket:
    customer = Customer()
    ...
class Customer:
    signature = FileField()
    name = CharField()

And I would like to use DRF's serializers to POST a new 'Ticket', so I send multipart/form data with the signature file AND the necessary 'application/json' data.

The resulting request, after collecting the FILES and DATA, looks like this:

>>> request.FILES
<MultiValueDict: {u'customer.signature': [<InMemoryUploadedFile: signature.jpg (image/jpeg)>]}>
>>> data
{u'customer': {u'name': u'Test'}, ... }
>>> serializer = TicketSerializer(data=data, files=request.FILES)
>>> serializer.is_valid()
False
>>> serializer.errors
{'customer': [{'signature': [u'This field is required.']}]}

How do I use the DRF Serializers/Fields to fill ImageFields/FileFields inside the 'customer' layer?

like image 482
steve-gregory Avatar asked Jun 06 '14 01:06

steve-gregory


1 Answers

Since it appears I'm not the only one who has this problem, this was the solution I came up with:

The most straight-forward answer is to take the uploaded ImageField/FileField and apply them into the appropriate position with the nested 'data' portion of the serializer. In my case, this would be inside the 'customer' dict.

Once the files have been properly applied to data, we can drop the 'files=' variable, since all the files are now included in data.

A working example in code would look something like this:

>>> request.FILES
<MultiValueDict: {u'customer.signature': [<InMemoryUploadedFile: signature.jpg (image/jpeg)>]}>
>>> data
{u'customer': {u'name': u'Test'}, ... }
if 'customer.signature' in request.FILES:
    data['customer']['signature_file'] = request.FILES['customer.signature']
>>> serializer = TicketSerializer(data=data)
>>> serializer.is_valid()
True
like image 178
steve-gregory Avatar answered Jan 04 '23 07:01

steve-gregory