DRF 3.0: UniqueTogetherValidator с полем только для чтения

в процессе обновления до Django Rest Framework 3.0 от 2.4.4, и я хочу иметь поле пользователя только для чтения, но это не удается, потому что "пользователь" требуется 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')

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

Итак, я продолжаю получать ошибки, говоря: {"user":["This field is required."]}, чего раньше не было. В немного другой пример с той же основной проблемой, я получаю ошибку утверждения May not set both 'read_only' and 'required' хоть я и не настройки пользователя.

Я получаю ту же ошибку, независимо от того, если я добавить required=False для атрибута user в сериализаторе или если я добавляю user в исключенные поля в meta сериализатора.

когда я использую удобный новый сериализатор печати, я вижу:

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

который автоматически добавляется на основе unique_together модели. если я явно перепишите это и не включайте "user" в поля для UniqueTogetherValidator тогда все работает по-прежнему.

является ли это предполагаемым следствием обновления 3.0? Мне кажется, что добавление request.user на perform_create / perform_update очень стандартная процедура DRF, как показано в учебнике. Я понимаю, что отсутствие новой проверки просто означает сбой на уровне БД, а новая проверка, вероятно, дает лучшие сообщения об ошибках, но

есть решение, отличное от переопределения проверки для каждого сериализатора, где это проблема?

заранее спасибо за любую помощь!

1 ответов


это известная проблема что мы находимся в процессе решения в рамках Django REST. На данный момент в документация по UniqueTogtherValidator что говорит

Примечание: на UniqueTogetherValidation класс всегда накладывает неявное ограничение, что все поля, к которым он применяется, всегда обрабатываются по мере необходимости. Поля default значения являются исключением из этого, поскольку они всегда предоставляют значение даже если опущено из пользовательского ввода.

это объясняет, почему вы видите ошибку, потому что поле требуется, даже если вы явно настройки read_only=True. Вы можете посмотреть в CurrentUserDefault класс, который может удовлетворить ваши потребности, избегая при этом проблемы с UniqueTogetherValidator.

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

    class Meta:
        model = ExampleModel

этой должны сделайте то же самое, что и ваш perform_create и perform_update крючки.