【问题标题】:Django Rest Framework: How to pass a list of UUIDs for a nested relationship to a serializer?Django Rest Framework:如何将嵌套关系的 UUID 列表传递给序列化程序?
【发布时间】:2018-06-20 06:50:33
【问题描述】:

TL;DR:我的一个序列化程序的传入数据未得到处理的原因可能是什么?

我正在为嵌套关系开发序列化程序。序列化程序应该得到一个 UUID 列表,这样我就可以建立多对多的关系。这是模型:

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

这是我在测试中使用的数据(我的帖子正文):

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)

请注意,custom_choice_items 的空列表不会改变任何内容。即使我用值填充它,也会发生相同的错误。最后但并非最不重要的是序列化程序:

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",
        ]

现在的问题是,当我忽略 many=True 时,我得到了错误:

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

如果我设置many=True,我只是没有得到任何数据。我的意思是例如序列化程序create() 方法中validated_data["custom_choice_items"] 的值只是空的。

这里出了什么问题?

我什至检查了请求中的数据 self.context["request"].data 包含一个键 custom_choice_items 我将数据传递到此视图的方式!

编辑:这是我传递给 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)

【问题讨论】:

  • uuidCustomChoiceItem 模型的主键吗?您可以分享已发布请求的正文吗?
  • @neverwalkaloner UUID 不是customchoiceitem 的主键。帖子请求的正文是数据中的内容(我编辑了帖子):)
  • 我的意思是你能添加你通过custom_choice_items 传递的内容吗?:) uuid 对 CustomChoiceItem 来说是唯一的吗?
  • @neverwalkaloner 当然我添加了它:)

标签: django django-rest-framework django-testing django-serializer django-tests


【解决方案1】:

当你使用测试api客户端发布数据时,如果数据包含嵌套结构你应该使用format=json,像这样:

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

【讨论】:

    【解决方案2】:

    您是否覆盖了序列化程序中的.create 方法?像这样的东西应该可以工作:

    from django.db import transaction
    
    class OrderSerializer(serializers.ModelSerializer):
        # your fields and Meta class here
    
        @transaction.atomic
        def create(self, validated_data):
            custom_choice_items = validated_data.pop('custom_choice_items')
            order = super().create(validated_data)
    
            order.custom_choice_items.add(*custom_choice_items)
            return order
    

    顺便说一句,如果CustomChoiceItemUUIDSerializer 只是其中的主键,您实际上并不需要定义。

    【讨论】:

    • 不,uuid 不是主键。这正是我所做的。我确实覆盖了.create(),但这条线custom_choice_items = validated_data.pop('custom_choice_items') 不起作用。如果我设置 many=True 并且没有 many=True 会引发字段必需错误,则它总是无。
    • 您应该为该自定义序列化程序添加many=True。如果这可能是一个空列表,则添加此allow_empty=True 以允许发送空列表,如果不需要该字段(您根本不发送),您也可以输入required=False
    • 我确实添加了many=True,但这无济于事。不管发生什么,我仍然没有任何价值。
    • 你可以试试这个吗? response = self.client.post(self.order_consumer_create_url, data, format='json')
    • 你这个字面上的神。我花了将近一天时间研究这个问题,唯一错误的是测试用例。非常感谢你!如果您将此评论作为答案发布,我会接受。
    猜你喜欢
    • 2016-09-25
    • 1970-01-01
    • 1970-01-01
    • 2016-12-18
    • 1970-01-01
    • 2016-12-30
    • 1970-01-01
    • 2017-03-12
    • 2017-05-24
    相关资源
    最近更新 更多