django-rest-framework - DRF 3.0 : UniqueTogetherValidator with a read-only field

标签 django-rest-framework

在从 2.4.4 升级到 Django REST Framework 3.0 的过程中,我想要一个只读用户字段,但这失败了,因为 UniqueTogetherValidator 需要“用户”(我认为)

我有模型(请原谅拼写错误,这是简化的,代码工作正常 IRL):

class ExampleModel(models.Model):
    some_attr = models.PositiveSmallIntegerField()
    other_attr = models.PositiveSmallIntegerField()
    user = models.ForeignKey(User)

    class Meta:
        unique_together = ('some_attr', 'other_attr', 'user')

View 集:
class ExampleViewSet(viewsets.ModelViewSet):
    queryset = ExampleModel.objects.all()
    serializer_class = ExampleSerializer

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

    def perform_update(self, serializer):
        serializer.save(user=self.request.user)

序列化器:
class ExampleSerializer(serializers.ModelSerializer):
    user = UserSerializer(read_only=True)

    class Meta:
        model = ExampleModel

现在,我不断收到错误消息:{"user":["This field is required."]} ,以前不是这样的。在具有相同基本问题的稍微不同的示例中,我收到断言错误 May not set both 'read_only' and 'required'即使我没有按要求设置用户。

无论我是否添加 required=False,我都会收到相同的错误对于序列化程序中的用户属性,或者如果我将用户添加到序列化程序元数据中的排除字段。

当我使用方便的新序列化程序打印时,我看到:
class Meta:
    validators = [UniqueTogetherValidator(queryset=ExampleModel.objects.all(), fields=('user', 'some_attr', 'other_attr'))]

它会根据模型的 unique_together 自动添加。如果我明确地覆盖它并且不在 UniqueTogetherValidator 的字段中包含“用户”然后一切都像以前一样工作。

这是 3.0 更新的预期结果吗?在我看来,添加 request.userperform_create/perform_update是非常标准的 DRF 程序,如教程中所示。我意识到没有新的验证只是意味着在数据库级别失败,而新的验证可能会提供更好的错误消息,但是

除了覆盖每个有问题的序列化程序的验证之外,还有其他解决方案吗?

提前感谢您的帮助!

最佳答案

这是a known issue我们正在 Django REST 框架中解决这个问题。截至目前,documentation about UniqueTogtherValidator 中有一条注释。说的是

Note: The UniqueTogetherValidation class always imposes an implicit constraint that all the fields it applies to are always treated as required. Fields with default values are an exception to this as they always supply a value even when omitted from user input.



这解释了为什么您会看到错误,因为该字段是必需的,即使您明确设置 read_only=True .您可能想查看 CurrentUserDefault class ,这可能会满足您的需求,同时避免 UniqueTogetherValidator 的问题.
class ExampleSerializer(serializers.ModelSerializer):
    user = UserSerializer(
        read_only=True
        default=serializers.CurrentUserDefault()
    )

    class Meta:
        model = ExampleModel

这应该和你的 perform_create 做同样的事情。和 perform_update钩子(Hook)。

关于django-rest-framework - DRF 3.0 : UniqueTogetherValidator with a read-only field,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27239382/

相关文章:

python - 测试模型序列化器

django - 嵌套网址不适用于 Django REST 框架

python - 如何从 Django Headers 获取数据?

python - : Django-rest-Framework 处的断言错误

django-rest-framework - 如何将权限类应用于 Django-Rest Framework 中基于类的 View 中的特定方法?

python - Django 休息框架 ModelSerializer

python - 嵌套关系序列化程序中的 Django Rest Framework 模型 Id 字段

django - 如何从 Django Rest 框架自定义身份验证类返回自定义响应对象

python - 如何在 Django Rest Framework 中实现一对多关系?

python - Django url 中的多个 pks