Django-rest-framework中的可写嵌套序列化器?

Tho*_*Liu 4 python django rest

我的设计如下关于Django ModelSerializer。有模型A和模型B。模型B有模型A的外键字段。由于某些原因,我不能直接使用主键来序列化模型B。我认为,我需要序列化其他两个字段(在模型A中唯一)。

而且我看到SlugRelatedField必须用于一个Slug字段。我搜索了一个NaturalKeyField可以支持NaturalKeyField。但看起来它被django-rest-framework取代。但是我检查了django-rest-framework,根本没有这样的领域。谁能帮忙?我该怎么办?

代码如下。型号A

class AssetModel(models.Model):
    org = models.ForeignKey(Org, related_name='models')
    name = models.CharField(max_length=128)
    model_type = models.SmallIntegerField(default = 3,choices = MODEL_TYPE )
    directory = models.CharField(max_length = 128)
    ...
    class Meta:
        unique_together = ('org', 'name',)
Run Code Online (Sandbox Code Playgroud)

B型

class Dataitem(models.Model):
    mod = models.ForeignKey(AssetModel, related_name='dataitems')
    name = models.CharField(max_length=128)
    data_type = models.SmallIntegerField(default =0,choices = DATAITEM_DATATYPE)
    ...
Run Code Online (Sandbox Code Playgroud)

模型A的序列化器

class AssetModelSerializer(serializers.ModelSerializer):
    org =  serializers.SlugRelatedField(queryset=Org.objects.all(), slug_field='name')
    class Meta:
        model = AssetModel
        fields = ('org', 'name', 'model_type',..
Run Code Online (Sandbox Code Playgroud)

模型B的序列化器

class DataitemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Dataitem
        fields = ('mod', 'name','data_type'...)
Run Code Online (Sandbox Code Playgroud)

模型A的主键只是Django自动添加的ID。序列化模型B时,我需要获取模型A的组织和名称。读和写都需要。

bak*_*kal 6

嵌套序列化器

您可以执行类似的操作,为其定义一个序列化程序,Dataitem以便可以重用AssetModel模型的序列化程序

class AssetModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = AssetModel

    # Fields org and name of AssetModel will be inlcuded by default

class DataitemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Dataitem

    mod = AssetModelSerializer()
        # This is the Dataitem.mod field
        # which is a FK to AssetModel,
        # Now it'll be serilized using the AssetModelSerializer
        # and include the org and name fields of AssetModelSerializer
Run Code Online (Sandbox Code Playgroud)

我更喜欢这种方法,因为我得到了控制。如果使用上述序列化,则会得到如下结构:

data_item = {'name': ..., 'mod': {'org': ..., 'name': ...}}
                          ^
                          |___ AssetModel fields
Run Code Online (Sandbox Code Playgroud)

另外,您也可以使用 depth = n

您也可以depth = 1Dataitem

class DataitemSerializer(serializers.ModelSerializer):
        class Meta:
            model = Dataitem
            depth = 1 # Will include fields from related models
                      # e.g. the mod FK to AssetModel
Run Code Online (Sandbox Code Playgroud)

可写嵌套序列化器

由于嵌套创建和更新的行为可能是模棱两可的,并且可能需要相关模型之间的复杂依赖关系,因此REST框架3要求您始终明确地编写这些方法。

我们必须create/update按照DRF的文档来实现使其可写

class DataitemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Dataitem

    # Nested serializer
    mod = AssetModelSerializer()

    # Custom create()
    def create(self, validated_data):
        # First we create 'mod' data for the AssetModel
        mod_data = validated_data.pop('mod')
        asset_model = AssetModel.objects.create(**mod_data)

        # Now we create the Dataitem and set the Dataitem.mod FK
        dataitem = Dataitem.objects.create(mod=asset_model, **validated_data)

        # Return a Dataitem instance
        return dataitem
Run Code Online (Sandbox Code Playgroud)


Ahm*_*mal 5

似乎有一个库可以执行此 drf-writable-nested

它处理这些类型的创建和序列化

  • 一对一(直接/反向)
  • 外键(直接/反向)
  • ManyToMany(直接/反向排除与直通模型的 m2m 关系)
  • GenericRelation(这总是相反的)