#python #django #django-rest-framework
#python #django #django-rest-framework
Вопрос:
Я начинаю изучать django (rest_framework) и создаю приложение. Я создал пользовательскую модель пользователя и менеджера, ниже кода:
class CustomUserManager(BaseUserManager):
"""Define a model manager for User model with no username field."""
def _create_user(self, email, password=None, **extra_fields):
"""Create and save a User with the given email and password."""
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password=None, **extra_fields):
"""Create and save a SuperUser with the given email and password."""
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(email, password, **extra_fields)
class CustomUser(AbstractUser):
email = models.EmailField(_('email address'), unique=True)
username = models.CharField(_('username'), max_length=255, unique=False, blank=True)
mobile = models.CharField(_('mobile'),max_length=255, blank=True)
picture = models.ImageField(upload_to='images/thumbnail/%Y/%m/%d/', null=True, blank=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
@property
def picture_preview(self):
if self.picture:
return mark_safe('<img src="{}" width="300" height="300" />'.format(self.picture.url))
return ""
objects = CustomUserManager()
Я также настроил представление для администратора .. и все работает нормально.
Теперь, когда я регистрирую нового пользователя от администратора и, например, дважды отправляю одно и то же электронное письмо, я получаю это сообщение об ошибке: пользователь с этим адресом электронной почты уже существует.
Но если я зарегистрирую нового пользователя с помощью postman для вызова API, я получу сообщение об ошибке ниже:
django.db.utils.IntegrityError: duplicate key value violates unique constraint "accounts_customuser_email_key"
DETAIL: Key (email)=(mario@mario.it) already exists.
Ниже класса сериализатора
class RegisterSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
email = serializers.EmailField()
class Meta:
model = CustomUser
fields = ['email', 'password']
def validate(self, attrs):
# Check if user exist
email = attrs.get('email', '')
# if CustomUser.objects.filter(email=email).exists():
# raise serializers.ValidationError(
# 'User with this Email address already exists.')
# Validate password
errors = dict()
user = CustomUser(**attrs)
password = attrs.get('password', '')
try:
# validate the password and catch the exception
validators.validate_password(password=password, user=user)
# the exception raised here is different than serializers.ValidationError
except ValidationError as e:
errors['password'] = list(e.messages)
if errors:
raise serializers.ValidationError(errors)
return attrs
def create(self, validated_data):
return CustomUser.objects.create_user(**validated_data)
В валидаторе я прокомментировал код, который проверяет, зарегистрировал ли пользователь это, потому что я ожидаю, что django должен знать, зарегистрирован ли email уже без дополнительного кода, поскольку в admin он работает без проблем.
и класс представления:
class RegisterView(generics.GenericAPIView):
serializers_class = RegisterSerializer
def post(self, request):
user = request.data
serializer = self.serializers_class(data=user)
serializer.is_valid(raise_exception=True)
serializer.save()
user_data = serializer.data
return Response(user_data, status.HTTP_201_CREATED)
Мой вопрос в том, делаю ли я что-то не так? Я что-то пропустил?
Спасибо всем … любая помощь будет оценена.
Ответ №1:
Если вы создаете пользователя с тем же адресом электронной почты, django проверяет и выдает IntegrityError. Вы должны перехватить это исключение и вернуть ответ. Также лучше, чтобы вы делали это в части представления, а не в методе проверки сериализатора, поскольку задача метода проверки сериализатора заключается только в проверке правильности заданных входных данных. итак, ваше представление должно выглядеть примерно так.
class RegisterView(generics.GenericAPIView):
serializers_class = RegisterSerializer
def post(self, request):
user = request.data
serializer = self.serializers_class(data=user)
serializer.is_valid(raise_exception=True)
try:
user = User.objects.create_user(
email=serializer.data.get("email"),
password=request.data.get("password"),
)
except IntegrityError:
return Response("Email already exists.",
status=status.HTTP_406_NOT_ACCEPTABLE,
)
response = jwt_response_payload_handler(user.get_jwt_token(), user, request) # some payload handler, for user information
return Response(response, status.HTTP_201_CREATED)