DRF 3.0: UniqueTogetherValidator with a read-only field

In the process of upgrading to Django REST Framework 3.0 with 2.4.4 and I want to have only a read-only user field, but this does not work, because the user UniqueTogetherValidator (I think) requires a "user"

I have a model (sorry 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 there before. In a slightly different example with the same underlying problem, I get a May not set both 'read_only' and 'required' assertion error, although I do not configure the user as needed.

I get the same error, regardless of whether I add required=False for the user attribute in the serializer or add the user to the excluded fields of the meta analyzer.

When I use the convenient new serialization, I see:

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

which is automatically added based on the unique_together model. If I explicitly overwritten this and did not include "user" in the fields for UniqueTogetherValidator , then everything will work as before.

Is this the intended consequence of update 3.0? It seems to me that adding request.user to perform_create / perform_update is a very standard DRF procedure, as shown in the tutorial. I understand that instead of just a new check, it simply means an error at the DB level, and the new check probably gives better error messages, but

Is there a solution other than overriding validation for each serializer if this is a problem?

Thanks in advance for your help!

+6
source share
1 answer

This is a known issue that we are in the process of accessing in the Django REST Framework. The document currently has a note on UniqueTogtherValidator that says

Note. The UniqueTogetherValidation class always sets an implicit restriction that all fields to which it is applied are always processed as needed. Fields with default values ​​are an exception to this, since they always give a value, even if they are not entered from user input.

This explains why you see the error because the field is required even if you are explicitly set to read_only=True . You might want to explore the CurrentUserDefault class, which can meet your needs, while avoiding the problem with UniqueTogetherValidator .

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

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

+7
source

Source: https://habr.com/ru/post/978969/


All Articles