django-rest-frameworkpytest-django

Pytest fails when trying to pass list of dictionaries in POST request


We have a model with only one fields (Name). We want to send a list of dictionaries and create multiple objects for this model in one POST request. The model, serializer, view and mixin is mentioned below:

models.py

class Manufacturer(models.Model):
    """
    The Measure Unit Category Table contains the categories
    of measurement units (example: weight, length, temperature,etc)
    """

    name = models.CharField(verbose_name=_("Manufacturer Name"),
                            help_text=_("Required. Example: Ford, Tesla, Hyundai"),
                            max_length=63,
                            unique=True)

    class Meta:
        verbose_name = _("Manufacturer")
        verbose_name_plural = _("Manufacturers")
        ordering = ('name',)

    def __str__(self):
        return self.name

serializers.py

class ManufacturerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Manufacturer
        fields = '__all__'

mixins.py

class CreateModelMixin(object):
    def get_serializer(self, *args, **kwargs):
        # add many=True if the data is of type list
        if isinstance(kwargs.get("data", {}), list):
            kwargs["many"] = True

        return super().get_serializer(*args, **kwargs)

views.py

class ManufacturerCreateView(CreateModelMixin, generics.CreateAPIView):
    """
    Create View for Manufacturer
    """

    queryset = Manufacturer.objects.all()
    serializer_class = ManufacturerSerializer
    permission_classes = (IsAuthenticated,)

With the above code, I'm able to create multiple objects with one POST request.

I've written the below test case using pytest:

def test_create_manufacturer_list_of_objects(self, authenticated_client):
        data = [
                {
                    "name": "Test11"
                },
                {
                    "name": "Test12"
                }
            ]

        response = authenticated_client.post(reverse('manufacturer-create'), data)
        assert response.status_code == 201

urls.py

path('create-manufacturer/',
         ManufacturerCreateView.as_view(),
         name='manufacturer-create'),

When I run the above, I get the error - AttributeError: 'list' object has no attribute 'items'. This is a little confusing as the API works without any errors but the test case fails. Can you please guide on correcting this issue?

I tried overriding the POST method, and including the above code in serializers instead of mixins, but it gives the same error.


Solution

  • Passing the "format=json" when calling the post method resolved the issue. Modified the test url to below:

     response = authenticated_client.post(reverse('manufacturer-create'), data, format=json)