如何在 django Rest Framework 嵌套序列化器中验证需要来自父级数据的子序列化器?

isA*_*Aif 8 django django-rest-framework

我正在使用DRF Writable Nested 创建可写嵌套序列化器。

我需要验证“ItemDetail”,但它需要父序列化程序(即“InvoiceItem”)中存在的“product_id”。

楷模

class InvoiceItem(models.Model):
    product = models.ForeignKey(
        Product, on_delete=models.CASCADE, related_name="invoice_items"
    )


class ItemDetail(models.Model):
    invoice_item = models.ForeignKey(
        InvoiceItem, on_delete=models.CASCADE, related_name="item_details"
    )
    size = models.ForeignKey(
        Size, on_delete=models.CASCADE, related_name="item_details"
    )
    quantity = models.PositiveIntegerField()
Run Code Online (Sandbox Code Playgroud)

序列化器

class InvoiceItemSerializer(WritableNestedModelSerializer):
    product = ProductMiniSerializer(read_only=True)
    product_id = serializers.IntegerField(write_only=True)
    item_details = ItemDetailSerializer(many=True)

    class Meta:
        model = InvoiceItem
        fields = [
            "id",
            "product_id",
            "product",
            "item_details",
        ]


class ItemDetailSerializer(serializers.ModelSerializer):

    class Meta:
        model = ItemDetail
        fields = [
            "id",
            "size",
            "quantity",
        ]

    def validate(self, data):
        return item_detail_validate(self, data)
Run Code Online (Sandbox Code Playgroud)

验证器

def item_detail_validate(self, data):
    # How to get product_id here so I can use it in a query
    return data
Run Code Online (Sandbox Code Playgroud)

小智 7

这有点晚了,但对于其他来到这里的人来说,在处理时请使用以下内容many=True

def validate(self, data):
    product_id = self.parent.parent.initial_data['product_id']
    return item_detail_validate(self, data)
Run Code Online (Sandbox Code Playgroud)

通常在进行相关引用时,self.parent.initial_data可以从父序列化器中获取数据。然而,当我们使用 时many=True,DRF 隐式调用ListSerializer. 它将子序列化器传递给ListSerializer,然后传递给父序列化器

参考: https: //www.django-rest-framework.org/api-guide/serializers/#listserializer

  • `.root` 也可用,它会爬上 `.parent` 树直到到达顶部 (2认同)

JPG*_*JPG 3

访问initial_data序列化器父级的属性,

def validate(self, data):
    product_id = self.parent.initial_data['product_id']
    return item_detail_validate(self, data)
Run Code Online (Sandbox Code Playgroud)