DRF 3.0:具有只读字段的UniqueTogetherValidator [英] DRF 3.0: UniqueTogetherValidator with a read-only field

查看:671
本文介绍了DRF 3.0:具有只读字段的UniqueTogetherValidator的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在从2.4.4升级到Django REST Framework 3.0的过程中,我想拥有一个只读用户字段,但是由于UniqueTogetherValidator需要user(我认为),这是失败的。

我有模型(借口拼写错误,这是简化的,代码工作正常的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')

Viewset:

  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

现在,我不断收到错误说: {用户:[此字段是必需的。]} ,其实不是这样。在具有相同基本问题的略有不同的示例中,我得到断言错误即使我没有根据需要设置用户,也可能不设置'read_only'和'required'



我收到相同的错误,无论我为序列化程序中的用户属性添加了 required = False ,或者我将用户添加到序列化程序的元数据中的排除字段。



当我使用方便的新的序列化程序打印时,我看到:

  class Meta:
validators = [UniqueTogetherValidator(queryset = ExampleModel.objects.all(),fields =('user','some_attr','other_attr' ))]

根据模型的unique_together自动添加。如果我明确地覆盖了这一点,并且在 UniqueTogetherValidator 的字段中不包含'user',那么一切都像以前一样。



perform_create / perform_update request.user c>是本教程中演示的非常标准的DRF过程。我意识到没有新的验证只是意味着在DB级别失败,新的验证可能会提供更好的错误消息,但



是否有解决方案其他而不是覆盖每个序列化程序的验证,这是一个问题?



提前感谢任何帮助!

解决方案

这是一个已知的问题,我们正在Django REST框架内处理过程。截至目前,有关UniqueTogtherValidator的文档


注意 UniqueTogetherValidation 类总是强加一个隐含的约束,它适用的所有字段总是被视为需要的。 默认值的字段是一个例外,因为它们总是提供一个值,即使从用户输入中省略。


这就解释了为什么你看到一个错误,因为该字段是必需的,即使你明确地设置了 read_only = True 。您可能需要查看 CurrentUserDefault class ,可以满足您的需要,同时避免使用 UniqueTogetherValidator 的问题。

 类ExampleSerializer(serializers.ModelSerializer):
user = UserSerializer(
read_only = True
default = serializers.CurrentUserDefault()


class Meta:
model = ExampleModel

>应该执行与 perform_create perform_update 挂钩相同的事情。


In process of upgrading to Django REST Framework 3.0 from 2.4.4 and I want to have a read-only user field, but this is failing because 'user' is being required by the UniqueTogetherValidator (I think)

I have model (excuse typos, this is simplified and the code works fine 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')

Viewset:

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)

Serializer:

class ExampleSerializer(serializers.ModelSerializer):
    user = UserSerializer(read_only=True)

    class Meta:
        model = ExampleModel

Now, I keep getting errors saying: {"user":["This field is required."]}, which was not the case before. In a slightly different example with the same basic problem, I get the assertion error May not set both 'read_only' and 'required' even though I am not setting user as required.

I receive the same error regardless if I add required=False for the user attribute in the serializer, or if I add user to the the excluded fields in the serializer's meta.

When I use the handy new serializer printing, I see:

class Meta:
    validators = [UniqueTogetherValidator(queryset=ExampleModel.objects.all(), fields=('user', 'some_attr', 'other_attr'))]

which gets automatically added based on the model's unique_together. If I explicitly overwrite this and do not include 'user' in the fields for UniqueTogetherValidator then everything works as before.

Is this an intended consequence of the 3.0 update? Seems to me that adding request.user in the perform_create / perform_update is very standard DRF procedure as demonstrated in the tutorial. I realize not having the new validation just means failing at the DB level instead, and the new validation probably gives better error messages, but

Is there a solution other than to override the validation for every serializer where this is an issue?

Thanks in advance for any help!

解决方案

This is a known issue that we are in the process of addressing within Django REST Framework. As of right now, there is a note in the documentation about UniqueTogtherValidator that says

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.

This explains why you are seeing an error because the field is required, even though you are explicitly settings read_only=True. You may want to look into the CurrentUserDefault class, which may suit your needs while avoiding the issue with the UniqueTogetherValidator.

class ExampleSerializer(serializers.ModelSerializer):
    user = UserSerializer(
        read_only=True
        default=serializers.CurrentUserDefault()
    )

    class Meta:
        model = ExampleModel

This should do the same thing as your perform_create and perform_update hooks.

这篇关于DRF 3.0:具有只读字段的UniqueTogetherValidator的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆