在django rest框架中为多级嵌套关系实现可写序列化程序

时间:2015-11-13 09:10:38

标签: django django-rest-framework

在drf3中,您现在可以通过覆盖create()方法并自己处理validated_data来实现可写嵌套序列化程序。但是,如果你在模型中有多级嵌套关系,那会怎么样:

class Order(models.Model):
    """
    Order model to aggregate all the shipments created by a user at a particular time.
    """
    created_at = models.DateTimeField(
        verbose_name='created at',
        auto_now_add=True
    )
    updated_at = models.DateTimeField(
        verbose_name='updated at',
        auto_now=True
    )

class Shipment(models.Model):
    """
    Many to One Relationship with the Orders Model. Aggregates all the details of a shipment being sent.
    """
    created_at = models.DateTimeField(
        verbose_name='created at',
        auto_now_add=True
    )
    updated_at = models.DateTimeField(
        verbose_name='updated at',
        auto_now=True
    )
    order = models.ForeignKey(
        to=Order
    )

class ItemDetail(models.Model):
    """
    Specifies details of the shipment contents. One to One relationship with the Shipment Model.
    """
    shipment = models.OneToOneField(
        to=Shipment,
        primary_key=True
    )
    CONTENT_TYPES = (
        ('D', 'Documents'),
        ('P', 'Products')
    )
    content = models.CharField(
        verbose_name='package contents',
        max_length=1,
        choices=CONTENT_TYPES,
        default='P'
    )

如何使用自定义create方法为订单编写序列化程序来处理这种情况?我见过的所有例子,包括官方页面上的例子都只有一层嵌套关系。

  

Read与depth参数一起正常工作。但是,我真的   感谢编写创建/更新方法的任何帮助。

2 个答案:

答案 0 :(得分:2)

writable nested serializer is explained in the documentation

请勿在创建/更新中重新创建新的序列化程序。 一旦您点击最顶层的序列化程序创建/更新,您的所有数据都将得到验证,包括嵌套的数据。

此时,您必须自己编写validated_data到各种对象的映射。

我试图让它自动用于DRF 2.x但事实证明有太多的用例,其中一些是独家的。因此,DRF离开了开发人员的工作 - 即你。

答案 1 :(得分:1)

一种方法是使用两个序列化程序,即ItemDetailSerializer,它们会调用ShipmentSirializer来处理OrderShipment创建,然后自己创建ItemDetail。< / p>

类似的东西:

class ItemDetailSerializer(serializers.ModelSerializer):
    """
    # Describe here all relationships
    """
    class Meta:
        model = ItemDetail

    def create(self, validated_data):

        shipment = validated_data.pop('shipment')
        shipment_serializer = ShipmentSerializer(data=shipment)
        if shipment_serializer.is_valid()
            shipment_serializer.save()

            item_detail = ItemDetail.objects.create(shipment=shipment_serializer.instance,
                                                    **validated_data)
            return item_detail

对于ShipmentSerializer,您可以按照有关嵌套关系的文档进行操作。