Django Rest Framework Serializers:从验证相关实体中排除

时间:2017-09-14 13:18:59

标签: django django-rest-framework

我有m2m相关实体:

class Tag(models.Model):
    name = models.CharField(
       max_length=80,
       blank=False,
       unique=True
)

class File(models.Model):
    tags = models.ManyToManyField(Tag)
    uploader = models.ForeignKey(User, on_delete=models.DO_NOTHING)

    name = models.CharField(
        max_length=255,
        blank=False,
        unique=True,
    )

和它们的序列化器:

class TagSerializer(serializers.ModelSerializer):
    class Meta:
        model = Tag
        fields = ('id', 'name')
        extra_kwargs = {
            'name': {
                'validators': [],
            },
        }

class FileSerializer(serializers.ModelSerializer):
    tags = TagSerializer(many=True, read_only=False)

    class Meta:
        model = File
        fields = ('id', 'name', 'tags')

    def update(self, instance, validated_data):
        tags_data = validated_data.pop('tags')

        if 'name' in validated_data:
           instance.name = validated_data['name']


        instance_tags = instance.tags.all()
        new_tag_list = []

        # add new tags
        for tag in tags_data:
            tag, created = Tag.objects.get_or_create(name=tag['name'])
            new_tag_list.append(tag)
            if tag not in instance_tags:
                instance.tags.add(tag)

        # remove old tags
        for instance_tag in instance_tags:
            if instance_tag not in new_tag_list:
                instance.tags.remove(instance_tag)

        return instance

正如您所看到的,我通过以下代码设置关闭了TagSerializer中Tag.name字段的所有验证:extra_kwargs = {'name': {'validators': []}} 这是因为在保存更新文件时出现验证错误:

serializer = FileSerializer(file, data=request.data, partial=True)
if serializer.is_valid(): 
    ...

如果您有包含标签列表的文件,并且只想添加或删除某些标签,则您将收到错误'此类名称的标签已存在'。

所以这个峰值工作正常,但是现在我没有对Tag.name进行唯一检查。 我试着写一些像FileSerializer中的内容:

class FileSerializer(serializers.ModelSerializer):
    class Meta:
       model = File
       extra_kwargs = {
           'tags': {
                'validators': [],
            },
        }

但当然不行。 问题是当我用文件添加/删除它的绑定时,根本不可能验证Tag实体。

2 个答案:

答案 0 :(得分:0)

您可以通过update的方式尝试,但如果此解决方案适合您,则还需要覆盖create方法。

class FileSerializer(serializers.ModelSerializer):
    tags = TagSerializer(many=True, read_only=True)
    #                                       ^^^^^^

    class Meta:
        model = File
        fields = ('id', 'name', 'tags')

    def update(self, instance, validated_data):
        # Override tags_data = validated_data.pop('tags')
        # this way
        request = self.context['request']
        tags_data = request.data.get('tags', [])

        # Next your current code
当您使用get_serializer方法添加的extra-context上下文时,

在序列化程序初始添加views from drf

serializer = FileSerializer(file, data=request.data, partial=True, context={'request': request})

答案 1 :(得分:0)

您还可以从实例中获取标签,无需通过上下文发送整个请求。

tags_data = self.initial_data.get('tags', [])