#django #django-rest-framework
#django #django-rest-framework
Вопрос:
class UserManager(BaseUserManager):
def create_user(self, username, email, password=None):
if username is None:
raise TypeError('User should have a username')
if email is None:
raise TypeError('User should have an email')
user = self.model(
username=username,
email=self.normalize_email(email)
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, email, password=None):
if password is None:
raise TypeError('Password should not be none')
user = self.create_user(username, email, password)
user.is_superuser = True
user.is_staff = True
user.save()
return user
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(
max_length = 255,
unique = True,
db_index = True
)
email = models.EmailField(
max_length = 255,
unique = True,
db_index = True
)
is_verified = models.BooleanField(default = False)
is_staff = models.BooleanField(default = True)
is_active = models.BooleanField(default = True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = UserManager()
def __str__(self):
return self.email
def tokens(self):
refresh = RefreshToken.for_user(self)
return {
'refresh': str(refresh),
'access': str(refresh.access_token)
}
class RegisterSerializer(serializers.ModelSerializer):
password = serializers.CharField(
max_length = 255,
min_length = 6,
write_only = True
)
class Meta:
model = User
fields = ['email', 'username', 'password']
extra_kwargs = {'password': {'write_only': True, 'min_length': 5}}
def validate(self, attrs):
email = attrs.get('email', '')
username = attrs.get('username', '')
if not username.isalnum():
raise serializers.ValidationError(
"Username should contain only alphanumeric characters"
)
return attrs
def create(self, validated_data):
return User.objects.create_user(**validated_data)
class RegisterView(generics.GenericAPIView):
permission_classes = (AllowAny,)
serializer_class = RegisterSerializer
def post(self, request):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
user_data = serializer.data
return Response(
serializer.data,
status=status.HTTP_201_CREATED
)
В настоящее время я использую django 3.1.3
и djangorestframework 3.12.2
. Хотя я могу войти в систему с суперпользователем и правильно получать токены, но не смог войти в систему с помощью штатных пользователей. От администратора Django я видел, что только у суперпользователя есть хэшированный пароль, а у всех остальных пользователей есть обычный текстовый пароль.
Ответ №1:
Вы не устанавливаете пароль с user.password
помощью , это просто текстовое поле в модели и работает как любое другое. Вы должны либо:
- предпочтительно: Позвонить
user.set_password(value)
- резервное копирование: вычислите пароль вручную, используя
make_password
перед сохранением
У вас уже есть create
метод, поэтому мы сначала поработаем с ним.
from django.contrib.auth.hashers import make_password
def create(self, validated_data):
pwd = validated_data.pop("password")
user = User.objects.create(**attrs)
user.set_password(pwd)
user.save(updated_fields=["password"])
return user
# or you could replace it in validated_data
def create(self, validated_data):
validated_data["password"] = make_password(validated_data["password"])
return User.objects.create(**attrs)
У вас есть процедура проверки, но она глобальная. Если вы укажете его конкретно в поле пароля, то сможете вычислить его там и оставить create
в покое. Люди обычно этого не делают, потому что стандартно также иметь поле «подтвердить пароль».
def validate_password(self, value):
# ...
return make_password(value)
Теперь, если вы хотите добавить confirm_password
поле, вам validate(self, attrs)
все равно нужно будет сравнить два поля, поэтому я бы рекомендовал отказаться от этого последнего метода.