Django REST Framework, pre_save() и serializer.is_valid(), как они работают?

Мне нужно приложить пользователя к запросу, это похоже на довольно распространенное дело, но оно оказывается почти невозможным.

Документы для Django REST Framework предлагают использовать метод pre_save класса serializer, который я сделал, но он не вызывается при вызове serializer.is_valid(), что делает его вроде бесполезным, поскольку без пользователя поле сериализатор не выполняет проверку.

Я видел несколько предложений, но они кажутся сумасшедшими хаками и/или не работают. Кроме того, я чувствую, что это слишком распространенная задача, которая действительно нуждается во всех вещах, которые я вижу, когда люди предлагают. Я не могу быть единственным человеком, которому нужно прикрепить пользователя к объекту, созданному в запросе REST.

Ответ 1

Оказалось, что проблема заключается в том, что я использовал ListAPIView в качестве базового класса для моего класса представления и не имеет метода pre_save. Когда я добавил некоторые из миксинов, которые определили, что все начинает работать.

Кажется странным, что что-то, что используется во многих базовых учебниках, не поддерживает такую ​​базовую функцию, а живет и учится.

Ответ 2

Предполагая, что вы используете один из описанных здесь механизмов аутентификации (или Django Auth):

http://django-rest-framework.org/api-guide/authentication.html, у вас есть

request.user объект.

Когда вы создаете сериализатор, вытащите его из запроса/передайте его при создании экземпляра.

MySerializer(data={"user": request.user, "otherField"=... })

Если вы делаете:

MySerializer(data=request.DATA)

Вам нужно скопировать объект request.DATA:

from django.utils.datastructures import MultiValueDict
...
data = MultiValueDict(request.DATA)
data['user'] = request.user
MySerializer(data=data)

Ответ 3

pre_save вызывается после is_valid, но до того, как экземпляр будет сохранен в базе данных. Вам необходимо переопределить проверку (используя def get_validation_exclusions(self): в этом поле сериализатора пользователя, так как вы исправите проблему проверки в pre_save. См. Мой предыдущий ответ здесь:

Поле сериализатора Django REST Framework обязательно = false

Я поднял его до авторов DRF, и они собираются исследовать более работоспособное решение.

Ответ 4

Лучшим решением этой проблемы является отметка обязательных полей, заполненных в pre_save как read_only_fields в сериализаторе.

Чтобы сделать это, добавьте следующее в класс сериализатора:

class MySerializer(serializers.ModelSerializer):
    ...
    class Meta:
        ...
        read_only_fields = ['user', 'my_other_field', ...]

Ответ 5

В новых версиях DRF (3.x) pre_save был заменен на perform_create и perform_update: Ссылка