序列化程序中的Django DRF重命名字段,但unique_together验证失败

问题描述 投票:2回答:1

在用于创建模型的序列化器中,我想将我的模型字段重命名为(field_name)_id,因此对于API使用者而言,该字段更是ID字段。该模型在某些字段上还具有unique_together约束。但是,当验证在序列化程序中运行时,它失败并显示KeyError字段不存在:

...rest_framework/utils/serializer_helpers.py", line 148, in __getitem__
    return self.fields[key]
KeyError: 'question'

是否有一种简单的方法可以使其正常工作?下面是最少的示例代码。

模型

class MyModel(Model):
            question = ForeignKey('uppley.Question', null=False, on_delete=PROTECT)
            user = ForeignKey('catalystlab.User', null=False, on_delete=PROTECT)

            class Meta:
                unique_together = ('question', 'user',)

Serializer

        class MyCreateSerializer(ModelSerializer):

            question_id = PrimaryKeyRelatedField(
                write_only=True,
                source='question',
                queryset=Question.objects.all(),
            )

            user_id = PrimaryKeyRelatedField(
                write_only=True,
                source='user',
                queryset=User.objects.all(),
            )

            class Meta:
                model = MyModel
                fields = ('question_id', 'user_id',)

test.py-测试用于演示目的

        question = QuestionFactory()
        user = UserFactory()

        data = {
            'question_id': question.id,
            'user_id': user.id,
        }
        serializer = MyCreateSerializer(data=data, write_only=True)
        is_valid = serializer.is_valid(raise_exception=True) #KeyError exception raised here.

以前使用DRF 3.10.3可以正常工作,但是现在使用3.11.0可以如上所述抛出KeyError。

我尝试过的

删除串行器中sourcePrimaryKeyRelatedFielduser_id上的question_id字段实际上导致绕过DRF中的unique_together验证,并避免了KeyError。但是,已验证的数据不会映射回原始字段名称(userquestion)。在这种情况下,我们必须先手动将密钥更改回其原始名称,然后才能从已验证的数据创建Model的实例。

有更好的方法吗?

django django-rest-framework
1个回答
0
投票

您可以制作自定义序列化器,如:-

class MyCreateSerializer(serializers.Serializer):

    question_id = serializers.PrimaryKeyRelatedField(
         write_only=True,
         queryset=Question.objects.all(),
    )

    user_id = PrimaryKeyRelatedField(
         write_only=True,
         queryset=User.objects.all(),
    )

并在其中创建用于创建对象的自定义创建函数。像:-

def create(self, validated_data):
    try:
        question = validated_data.get('question_id')
        user = validated_data.get('user_id')
        instance = MyModel.objects.create(question=question, user=user)
    except TypeError:
        raise TypeError("Something went wrong while creating objects")

    return instance
© www.soinside.com 2019 - 2024. All rights reserved.