如何在 DRF 中通过另一个序列化程序自定义嵌套字段序列化程序

how to customize nested fields serializer through another serializer in drf

提问人:ali ebrahimyan 提问时间:11/3/2023 更新时间:11/3/2023 访问量:17

问:

File 类和 Animation 是相关的 我想以某种方式实现以下代码或serial = AnimationSerializer(instance=Animation.objects.get(id=animationn_id), fields=["duration", "age_rating", {"file": ["name", "description"]}])serial = FileSerializer(instance=File.objects.get(id=file_id), fields=["name", "description", {"animations": {"fields": ["duration", "made_by"], "many": True, "read_only": False}}])

实际上我不想写几个序列化程序类。 我想编写尽可能少的代码来实现这一目标。

我想使用 2 个序列化程序为两个模型实现创建、检索和更新的方法,以便我可以使用两个序列化程序之一来创建、检索和更新该模型的实例。

我有两个简单的模型:

class File(models.Model):
    video = 1
    PDF = 2
    word = 3
    all_types = (
    (video, "video"),
    (PDF, "PDF"),
    (word, "word"),
    )
    type = models.PositiveSmallIntegerField(choices=all_types)
    name = models.CharField(max_length=30)
    description = models.CharField(max_length=50)

class Animation(models.Model):
    file = models.ForeignKey("File", on_delete=models.CASCADE, related_name="animations")
    duration = models
    made_by = models..CharField(max_length=30)
    age_rating = models.PositiveSmallIntegerField(validators=[validators.MaxValueValidator(24)])

我有这些序列化程序类:

class DynamicFieldsCategorySerializer(serializers.ModelSerializer):
    def __init__(self, *args, **kwargs):
        # Don't pass the 'fields' arg up to the superclass
        fields = kwargs.pop('fields', None)

        # Instantiate the superclass normally
        super().__init__(*args, **kwargs)

        if fields is not None:
            # Drop any fields that are not specified in the `fields` argument.
            allowed = set(fields)
            existing = set(self.fields)
            for field_name in existing - allowed:
                self.fields.pop(field_name)

class FileSerializer(DynamicFieldsCategorySerializer):
    class Meta:
        model = File
        fields = "__all__"

class AnimationSerializer(DynamicFieldsCategorySerializer):
    file = FileSerializer(many=True)
    class Meta:
        model = Animation
        fields = "__all__"

根据这个问题,我编写了 DynamicFieldsCategorySerializer 类来自定义 AnimationSerializer 字段。但我想通过 AnimationSerializer 对 FileSerializer 进行 costomize

检索方法的一种方法是:

class FileSerializer(DynamicFieldsCategorySerializer):
    animations = AnimationSerializer(read_only=True, many=True)
    class Meta:
        model = File
        fields = "__all__"
    animation_fields = []
    def get_animations(self, obj):
        return AnimationSerializer(many=True, read_only=True, instance=obj.animations, fields=self.animation_fields).data

并以这种方式获取数据:

serial = FileSerializer(instance=File.objects.get(id=file_id))
serial.animation_fields.extend(["name", "description"])
serial.data

但这种方式只适用于检索方法,我想做所有 CRUD 方法 我认为可以通过在源代码 django rest framwork 中覆盖 build_fieldbuild_nested_field、**get_nested_relation_kwargs **来实现 我认为这样的目标可以通过覆盖 Django Rest 框架源代码中的 build_fieldbuild_nested_fieldget_nested_relation_kwargs方法来实现。但我不知道怎么做

Django django-rest-framework 反序列化 crud

评论


答: 暂无答案