在从 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.user
在 perform_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 withdefault
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/