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
:
Ссылка