10

In 2.x we had a serializer which looked like:

class FooSerializer(serializers.ModelSerializer):
    bar = serializers.PrimaryKeyRelatedField()

    class Meta:
        model = Foo

This effectively was able to handle bulk creates (passing a list as the body of a JSON post request). In 3.x, this endpoint is broken. I've tried to implement something similar to the docs on DRF

class FooListSerializer(serializers.ListSerializer):
    def create(self, validated_data):
        foos = [Foo(**item) for item in validated_data]
        return Foo.objects.bulk_create(foos)

class FooSerializer(serializers.ModelSerializer):
    bar = serializers.PrimaryKeyRelatedField(
        queryset=Bar.objects.all()
        )

    class Meta:
        model = Foo
        list_serializer_class = FooListSerializer

And while this works for a single create request, when I attempt to pass a list I get the error:

AttributeError: 'FooListSerializer' object has no attribute 'object'

I've seen some hacks where __init__ is super'd, but it seems with the creation of the ListSerializer class in 3.x there has to be a cleaner way to do this. Thanks in advance.

Quentin Donnellan
  • 2,687
  • 1
  • 18
  • 24
  • 1
    Possible duplicate of [How to post/put json data to ListSerializer](http://stackoverflow.com/a/27871396/359284). You can find my detailed answer there, with examples for how to handle bulk create/update/delete. – Kevin Brown-Silva Jan 13 '15 at 03:30
  • Actually I was just about to comment on your very question - your solution worked for me (thanks a ton), and I do believe these are related, but I suspect that the "canonical" solution has actually not been implemented yet? – Quentin Donnellan Jan 13 '15 at 03:52
  • I should mention that your previous way has been broken since 2.4, when DRF removed the ability for a list to be interpreted as `many=True` automatically. – Kevin Brown-Silva Jan 13 '15 at 03:56
  • Yeah we were actually using the Bulk mixin on the associated viewset to force it to work – Quentin Donnellan Jan 13 '15 at 03:59
  • 4
    Late to the party but suggest marking the question as answered if you have a solution - took me a while to spot your comment. – Dwight Gunning Sep 07 '16 at 07:11
  • Possible duplicate of [How can i bulk create in django rest serializer](https://stackoverflow.com/questions/33826742/how-can-i-bulk-create-in-django-rest-serializer) – Vaibhav Mule Sep 19 '17 at 07:43

1 Answers1

8

You don't show how your code is making a FooSerializer instance. The Django REST Framework 3 documentation says:

To serialize a queryset or list of objects instead of a single object instance, you should pass the many=True flag when instantiating the serializer. You can then pass a queryset or list of objects to be serialized.

So, it seems that your code should detect whether the data contains one instance or many, and:

  • serializer = FooSerializer() to handle one instance, or
  • serializer = FooSerializer(many=True) to handle a list of many instances.

Explicit is better than implicit :-)

bignose
  • 30,281
  • 14
  • 77
  • 110
  • The documentation link now 404s, you can find the updated link here: http://www.django-rest-framework.org/api-guide/serializers/#dealing-with-multiple-objects – Raphaël Gomès May 15 '18 at 12:22
  • Boo, documentation URLs should not change. Thanks for the note @raphaël-gomès, I have updated the answer now. – bignose May 15 '18 at 19:04