Search code examples
djangodjango-rest-frameworkdjango-testingdjango-serializerdjango-tests

Django Rest Framework: How to pass a list of UUIDs for a nested relationship to a serializer?


TL;DR: What could be the reason the incoming data for one of my serializers does not get processed?

I'm working on a serializer for a nested relationship. The serializer should get a list of UUIDs, so that I can make many to many relationships. Here is the model:

class Order(
    UniversallyUniqueIdentifiable,
    SoftDeletableModel,
    TimeStampedModel,
    models.Model
):
    menu_item = models.ForeignKey(MenuItem, on_delete=models.CASCADE)
    custom_choice_items = models.ManyToManyField(CustomChoiceItem, blank=True)
    price = models.ForeignKey(MenuItemPrice, on_delete=models.CASCADE)
    amount = models.PositiveSmallIntegerField(
        validators=[MinValueValidator(MINIMUM_ORDER_AMOUNT)]
    )

Here is the data (my post body) with which I hit the route in my tests:

data = {
    "checkin_uuid": self.checkin.uuid,
    "custom_choice_items": [],
    "menu_item": self.menu_item.uuid,
    "price": self.menu_item_price.uuid,
    "amount": ORDER_AMOUNT,
}
response = self.client.post(self.order_consumer_create_url, self.data)

Note that the empty list for custom_choice_items does not change anything. Even if I fill it with values the same error occurs. And last but not least here are the serializers:

class CustomChoiceItemUUIDSerializer(serializers.ModelSerializer):
    """Serializer just for the uuids, which is used when creating orders."""
    class Meta:
        model = CustomChoiceItem
        fields = ["uuid"]
....
# The serializer that does not work
class OrderSerializer(serializers.ModelSerializer):
    menu_item = serializers.UUIDField(source="menu_item.uuid")
    custom_choice_items = CustomChoiceItemUUIDSerializer()
    price = serializers.UUIDField(source="price.uuid")
    wish = serializers.CharField(required=False)

    class Meta:
        model = Order
        fields = [
            "uuid",
            "menu_item",
            "custom_choice_items",
            "price",
            "amount",
            "wish",
        ]

The problem is now, that when I leave out many=True, I get the error:

{'custom_choice_items': [ErrorDetail(string='This field is required.', code='required')]}

And If I set many=True I just simply don't get any data. By that I mean e.g. the value of validated_data["custom_choice_items"] in the serializers create() method is just empty.

What goes wrong here?

I even checked that the data is in the request self.context["request"].data includes a key custom_choice_items the way I pass the data to this view!

EDIT: Here is the data I pass to custom_choice_items:

   data = {
       “checkin_uuid”: self.checkin.uuid,
       “custom_choice_items”: [{“uuid”: custom_choice_item.uuid}],
       “menu_item”: self.menu_item.uuid,
       “price”: self.menu_item_price.uuid,
       “amount”: ORDER_AMOUNT,
   }
   self.client.credentials(HTTP_AUTHORIZATION=“Token ” + self.token.key)
   response = self.client.post(self.order_consumer_create_url, data)

Solution

  • When you post data using the test api client, if the data contains nested structure you should use format=json, like this:

    response = self.client.post(self.order_consumer_create_url, data, format='json')