django-rest-auth:自定义注册序列化程序不保存自定义字段
django-rest-auth: Custom Register Serializer not saving custom fields
NOT A DUPLICATE
我正在使用 Django
和 ReactJs
构建一个简单的 Todo
应用程序,我 运行 遇到了 django-rest-auth
的问题。
问题是我的自定义 UserRegisterSerializer
只保存了 request.data
的一个片段而忽略了其余部分。我不知道为什么。
这是我的代码:
用户模型:
class User(AbstractUser):
id = models.UUIDField(default=uuid.uuid4,
primary_key=True, unique=True, editable=False, db_index=True)
first_name = models.CharField(max_length=100, blank=False)
last_name = models.CharField(max_length=100, blank=False)
email = models.EmailField(max_length=247, blank=False,
unique=True, error_messages={
'unique': _('A user with this email already exists.'),
'invalid': _('Invalid e-mail address detected.'),
'blank': _('this field may not be blank.')
})
phone = models.CharField(max_length=20, blank=True, null=True,
unique=True, error_messages={
'unique': _('A user with this phone number already exists.'),
})
gender = models.CharField(max_length=5, choices=GENDERS, default=NOOP)
birthday = models.DateField(blank=True, null=True)
@property
def user_id(self):
return self.id
RegisterSerializer(自定义):
class UserRegisterSerializer(RegisterSerializer):
first_name = serializers.CharField(
write_only=True, required=True, max_length=100)
last_name = serializers.CharField(
write_only=True, required=True, max_length=100)
birthday = serializers.DateField(required=True, write_only=True)
phone = serializers.CharField(max_length=20, write_only=True,
validators=[
UniqueValidator(
User.objects.all(),
message=_('A user with this phone number already exists.')
)
])
gender = serializers.ChoiceField(
write_only=True,
choices=[
('NO-OP', 'Rather not tell'),
('M', 'Male'),
('F', 'Female'),
],
default='NO-OP'
)
def get_cleaned_data(self):
cleaned_data = super().get_cleaned_data()
cleaned_data['first_name'] = self.validated_data.get('first_name', '')
cleaned_data['last_name'] = self.validated_data.get('last_name', '')
cleaned_data['phone'] = self.validated_data.get('phone', '')
cleaned_data['birthday'] = self.validated_data.get('birthday', '')
cleaned_data['gender'] = self.validated_data.get('gender', '')
print(cleaned_data)
return cleaned_data
print(cleaned_data)
的输出:
{'username': 'john_doe', 'password1': 'djangopass', 'email': 'john_doe@email.com', 'first_name': 'John', 'last_name': 'Doe', 'phone': '+555 555 5555', 'birthday': datetime.date(2020, 6, 3), 'gender': 'M'}
保存的用户模型:
saved_model_image
我使用自定义 UserAdapter
解决了这个问题。
这是adapter.py
的代码:
from allauth.account.adapter import DefaultAccountAdapter
from allauth.account.utils import user_field
class UserAdapter(DefaultAccountAdapter):
def save_user(self, request, user, form, commit=True):
data = form.cleaned_data
birthday = data.get('birthday')
phone = data.get('phone')
gender = data.get('gender')
if birthday:
setattr(user, 'birthday', birthday)
if phone:
user_field(user, 'phone', phone)
if gender:
user_field(user, 'gender', gender)
return super().save_user(request, user, form, commit=commit)
然后在你的 settings.py
:
...
ACCOUNT_ADAPTER = 'accounts.adapter.UserAdapter'
...
我使用 CustomRegisterSerializer 中的保存方法调用默认保存方法并更新属性,例如:
我需要填写姓名和个人资料:
class CustomRegisterSerializer(RegisterSerializer):
first_name = serializers.CharField(required=True)
last_name = serializers.CharField(required=True)
profile = serializers.IntegerField(required=True)
def get_cleaned_data(self):
super(CustomRegisterSerializer, self).get_cleaned_data()
return {
'first_name': self.validated_data.get('first_name', ''),
'last_name': self.validated_data.get('last_name', ''),
'email': self.validated_data.get('email', ''),
'password1': self.validated_data.get('password1', ''),
'id': self.validated_data.get('id', ''),
'profile': self.validated_data.get('profile','')
}
def save(self, request):
user = super().save(request)
user.profile = self.data.get('profile')
user.save()
return user
NOT A DUPLICATE
我正在使用 Django
和 ReactJs
构建一个简单的 Todo
应用程序,我 运行 遇到了 django-rest-auth
的问题。
问题是我的自定义 UserRegisterSerializer
只保存了 request.data
的一个片段而忽略了其余部分。我不知道为什么。
这是我的代码:
用户模型:
class User(AbstractUser):
id = models.UUIDField(default=uuid.uuid4,
primary_key=True, unique=True, editable=False, db_index=True)
first_name = models.CharField(max_length=100, blank=False)
last_name = models.CharField(max_length=100, blank=False)
email = models.EmailField(max_length=247, blank=False,
unique=True, error_messages={
'unique': _('A user with this email already exists.'),
'invalid': _('Invalid e-mail address detected.'),
'blank': _('this field may not be blank.')
})
phone = models.CharField(max_length=20, blank=True, null=True,
unique=True, error_messages={
'unique': _('A user with this phone number already exists.'),
})
gender = models.CharField(max_length=5, choices=GENDERS, default=NOOP)
birthday = models.DateField(blank=True, null=True)
@property
def user_id(self):
return self.id
RegisterSerializer(自定义):
class UserRegisterSerializer(RegisterSerializer):
first_name = serializers.CharField(
write_only=True, required=True, max_length=100)
last_name = serializers.CharField(
write_only=True, required=True, max_length=100)
birthday = serializers.DateField(required=True, write_only=True)
phone = serializers.CharField(max_length=20, write_only=True,
validators=[
UniqueValidator(
User.objects.all(),
message=_('A user with this phone number already exists.')
)
])
gender = serializers.ChoiceField(
write_only=True,
choices=[
('NO-OP', 'Rather not tell'),
('M', 'Male'),
('F', 'Female'),
],
default='NO-OP'
)
def get_cleaned_data(self):
cleaned_data = super().get_cleaned_data()
cleaned_data['first_name'] = self.validated_data.get('first_name', '')
cleaned_data['last_name'] = self.validated_data.get('last_name', '')
cleaned_data['phone'] = self.validated_data.get('phone', '')
cleaned_data['birthday'] = self.validated_data.get('birthday', '')
cleaned_data['gender'] = self.validated_data.get('gender', '')
print(cleaned_data)
return cleaned_data
print(cleaned_data)
的输出:
{'username': 'john_doe', 'password1': 'djangopass', 'email': 'john_doe@email.com', 'first_name': 'John', 'last_name': 'Doe', 'phone': '+555 555 5555', 'birthday': datetime.date(2020, 6, 3), 'gender': 'M'}
保存的用户模型:
saved_model_image
我使用自定义 UserAdapter
解决了这个问题。
这是adapter.py
的代码:
from allauth.account.adapter import DefaultAccountAdapter
from allauth.account.utils import user_field
class UserAdapter(DefaultAccountAdapter):
def save_user(self, request, user, form, commit=True):
data = form.cleaned_data
birthday = data.get('birthday')
phone = data.get('phone')
gender = data.get('gender')
if birthday:
setattr(user, 'birthday', birthday)
if phone:
user_field(user, 'phone', phone)
if gender:
user_field(user, 'gender', gender)
return super().save_user(request, user, form, commit=commit)
然后在你的 settings.py
:
...
ACCOUNT_ADAPTER = 'accounts.adapter.UserAdapter'
...
我使用 CustomRegisterSerializer 中的保存方法调用默认保存方法并更新属性,例如:
我需要填写姓名和个人资料:
class CustomRegisterSerializer(RegisterSerializer):
first_name = serializers.CharField(required=True)
last_name = serializers.CharField(required=True)
profile = serializers.IntegerField(required=True)
def get_cleaned_data(self):
super(CustomRegisterSerializer, self).get_cleaned_data()
return {
'first_name': self.validated_data.get('first_name', ''),
'last_name': self.validated_data.get('last_name', ''),
'email': self.validated_data.get('email', ''),
'password1': self.validated_data.get('password1', ''),
'id': self.validated_data.get('id', ''),
'profile': self.validated_data.get('profile','')
}
def save(self, request):
user = super().save(request)
user.profile = self.data.get('profile')
user.save()
return user