В моем проекте у меня есть два «типа» пользователей: клиенты и предприятия. Они являются расширением django базового пользователя от django.contrib.auth.models.User
.
У меня есть в моем models.py
:
class Customer(models.Model):
user = models.OneToOneField(User, related_name='user', on_delete=models.CASCADE)
birth_date = models.DateField(blank=True, null=True)
phone = PhoneNumberField(unique=True)
def __str__(self):
return self.user.username
class Business(models.Model):
user = models.OneToOneField(User, related_name='business', on_delete=models.CASCADE)
cf = models.CharField(max_length=16, validators=[ssn_validation])
birth_date = models.DateField(null=True)
city = models.CharField(max_length=50, blank=False)
address = models.CharField(max_length=150, blank=False)
Хорошо, тогда у меня есть две разные регистрации, одна для Клиенты и один для бизнеса. Проблема в том, что для проверки пароля, отправленного из REST API, мне нужно сравнить password
с password2
, создать пользователя (django base) и передать его в мой Customer.objects.create, например: :
У меня в serializers.py
:
class CustomerRegistationSerializer(serializers.ModelSerializer):
username = serializers.CharField(source='user.username',
validators=[UniqueValidator(queryset=User.objects.all())])
email = serializers.CharField(source='user.email',
validators=[UniqueValidator(queryset=User.objects.all())])
first_name = serializers.CharField(source='user.first_name')
last_name = serializers.CharField(source='user.last_name')
password = serializers.CharField(source='user.password', write_only=True)
password2 = serializers.CharField(style={'input_style': 'password'}, write_only=True)
birth_date = serializers.CharField(required=False)
class Meta:
model = Customer
fields = ['id', 'username', 'email', 'password', 'password2', 'first_name', 'last_name',
'birth_date', 'phone']
def save(self):
username = self.validated_data['user']['username']
password = self.validated_data['user']['password']
password2 = self.validated_data['password2']
email = self.validated_data['user']['email']
first_name = self.validated_data['user']['first_name']
last_name = self.validated_data['user']['last_name']
phone = self.validated_data['phone']
try:
birth_date = self.validated_data['birth_date']
except KeyError:
birth_date = None
if password != password2:
raise serializers.ValidationError({'password': 'Passwords must match!'})
user = User.objects.create(username=username, email=email, first_name=first_name, last_name=last_name)
user.set_password(password)
user.is_active = False
user.save()
customer = Customer.objects.create(user=user,
birth_date=birth_date,
phone=phone)
return customer
Это на самом деле работает, но в случае ошибок может произойти, что пользователь создан, а клиент - нет. Есть ли более чистый способ регистрации клиентов, всегда проверяющий password == password2
?
РЕДАКТИРОВАТЬ: Я нашел более элегантный способ справиться с этим:
@ транзакция. atomic def save (self): password = self.validated_data ['user'] ['password'] password2 = self.validated_data ['password2']
user = User.objects.create(**self.validated_data['user'])
if password != password2:
raise serializers.ValidationError({'password': 'Passwords must match!'})
user.set_password(password)
user.is_active = False
user.save()
update_last_login(None, user)
del self.validated_data['user']
del self.validated_data['password2']
customer = Customer.objects.create(user=user, **self.validated_data)
return customer