Quentin Donnellan
Quentin Donnellan

Reputation: 2832

Canonical way to do bulk create in django-rest-framework 3.x?

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.

Upvotes: 10

Views: 9712

Answers (1)

bignose
bignose

Reputation: 32357

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 :-)

Upvotes: 8

Related Questions