Django rest framework создать пользователя с паролем
Использование django-rest-framework 3 и django 1.8
Я пытаюсь создать пользователя с помощью django-rest-framework ModelViewSerializer. проблема в том, что метод objects.create по умолчанию, используемый DRF, оставляет пароль как обычный текст.
Проблема заключается в том, что метод создания серийного файла DRF использует метод objects.create
querysets/#create вместо использования метода objects.create_user
.
код serializers.py строка 775
instance = ModelClass.objects.create(**validated_data)
Какое лучшее решение для этого? Я могу переопределить метод serializer.create для использования objects.user_create вместо objects.create, но он не похож на правильное решение.
остальная часть кода:
from django.contrib.auth.models import User
from rest_framework import viewsets
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'email','password')
write_only_fields = ('password',)
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer = UserSerializer()
Ответы
Ответ 1
вы можете переопределить create
в UserSerilizer:
class UserSerializer(serializers.ModelSerializer):
# ....
def create(self, validated_data):
user = User.objects.create_user(**validated_data)
return user
другие решения могут переопределять perform_create
в классе ViewSet, или вы можете написать свой собственный метод create
в вашем классе вида
class UserViewSet(viewsets.ModelViewSet):
def create(self, request, format=None):
# create user here
# do not call seriailzer.save()
UPDATE: после комментария @freethebees, также отменяется переопределение perform_create
, поэтому вот фрагмент кода:
class UserViewSet(viewsets.ModelViewSet, mixins.CreateModelMixin):
def perform_create(self, serializer):
# use User.objects.create_user to create user
pass
Примечание:
этот ответ дает 3 решения, выберите тот, который, по вашему мнению, лучше соответствует вашим потребностям и экосистеме вашего проекта.
ПРИМЕЧАНИЕ 2
Я лично предпочитаю переопределять create
в UserViewSet
(второй фрагмент кода), потому что вы можете просто вернуть свой пользовательский Response
(например, вернуть профиль пользователя после входа в систему)
Ответ 2
Есть еще лучший вариант для проверки пароля в serializer
from django.contrib.auth.hashers import make_password
class UserSerializer(serializers.ModelSerializer):
def validate_password(self, value: str) -> str:
return make_password(value)
Ответ 3
В дополнение к ответу @aliva, где вы упускаете функциональные возможности в serializers.Modelserializer.create()
(что было бы неплохо сохранить, например, обрабатывает отношения "многие ко многим"), есть способ сохранить это.
Используя метод user.set_password()
, пароль также может быть правильно установлен, например:
class UserSerializer(serializers.ModelSerializer):
def create(self, validated_data):
user = super().create(validated_data)
user.set_password(validated_data['password'])
user.save()
return user
Это имеет преимущество сохранения функциональности суперкласса, но является недостатком дополнительной записи в базу данных. Решите, какой компромисс для вас важнее :-).
Редактировать: Исправить синтаксическую ошибку