I try implement registration endpoint for user with additional attributes like phone_number and full_name.
I implement the logic for saving user data, which come from request, but I can't understand how I can save profile data, like phone_number and full_name.
I have a user model:
class User(AbstractUser):
email = models.EmailField(_('email address'), unique=True)
is_verified = models.BooleanField(_('is verified by admin'), default=False)
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = UserManager()
def __str__(self):
return self.email
def save(self, *args, **kwargs):
if not self.username:
self.set_username()
super().save(*args, **kwargs)
def email_user(self, subject, message, from_email=None, **kwargs):
"""Send an email to this user."""
send_mail(subject, message, from_email, [self.email], **kwargs)
def set_username(self):
pass
And profile model:
class Profile(TimeStampedModel):
STATUS = Choices(
("inactive", _("inactive")),
("active", _("active")),
("banned", _("banned"))
)
user = models.OneToOneField(
User,
verbose_name=_('related user'),
on_delete=models.CASCADE,
related_name='profile',
related_query_name='profile'
)
description = models.TextField(
_("description of user's profile"),
blank=True,
default=''
)
status = StatusField(
_("status of the user")
)
birth_date = models.DateField(
_("Date of birth"),
validators=[
MinValueValidator(
datetime.date(1910, 1, 1)
),
MaxValueValidator(
datetime.date.today
)
],
null=True,
blank=True
)
avatar = models.OneToOneField(
"files.Avatar",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="profile"
)
full_name = models.CharField(
max_length=30,
default='',
blank=False
)
phone_number_regex_validator = RegexValidator(regex=COMPILED_REGEXP)
phone_number = models.CharField(
max_length=16,
default='',
blank=False,
validators=[phone_number_regex_validator]
)
objects = ProfileQuerySet.as_manager()
def __str__(self):
return f"profile of user {self.user_id}"
class Meta:
verbose_name = _('profile')
verbose_name_plural = _('profiles')
Here is my serealizer for users:
class RegisterSerializer(serializers.Serializer): # pylint: disable=abstract-method
email = serializers.EmailField(
required=True, help_text=_('Email address')
)
password1 = serializers.CharField(
write_only=True, help_text=_('Password')
)
password2 = serializers.CharField(
write_only=True, help_text=_('Password Confirmation')
)
phone_number = serializers.CharField(
write_only=True, help_text=_('Phone number')
)
full_name = serializers.CharField(
write_only=True, help_text=_('Full name')
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.cleaned_data = {}
@staticmethod
def validate_email(email):
email = get_adapter().clean_email(email)
if email and email_address_exists(email):
raise serializers.ValidationError(_(
"A user is already registered with this e-mail address.")
)
return email
@staticmethod
def validate_password1(password):
return get_adapter().clean_password(password)
def validate(self, attrs):
if attrs['password1'] != attrs['password2']:
raise serializers.ValidationError(_(
"The two password fields didn't match.")
)
return attrs
def custom_signup(self, request, user):
pass
def get_cleaned_data(self):
return {
'password1': self.validated_data.get('password1', ''),
'email': self.validated_data.get('email', ''),
'phone_number': self.validated_data.get('phone_number', ''),
'full_name': self.validated_data.get('full_name', '')
}
def save(self, request): # pylint: disable=arguments-differ
adapter = get_adapter()
user = adapter.new_user(request)
self.cleaned_data = self.get_cleaned_data()
adapter.save_user(request, user, self)
self.custom_signup(request, user)
setup_user_email(request, user, [])
return user
And signals where profile object created and save to db:
@receiver(post_save, sender=User)
def create_user_profile(sender, instance=None, created=False, **kwargs):
if created:
Profile.objects.create(user=instance)
How i can save all neded attrs for model profile in the db?