[英]Django-Allauth - Errors with custom User model and custom Signup form
我正在嘗試使用自定義用戶模型實現django-allauth ,但是在新用戶注冊時我不斷收到錯誤消息。 以下是我的用戶模型:
# models.py
class User(AbstractUser):
name = models.CharField(_("Name of User"), blank=True, max_length=255)
tier = models.CharField(_("Plan"), choices=TIER_CHOICES, default='FREE', max_length=5)
dateOfBirth = models.DateField(_("Date of birth"), auto_now=False, auto_now_add=False)
gender = models.CharField(_('Gender'), choices=GENDER_CHOICES, default='MASC', max_length=5)
city = models.CharField(_("City"), max_length=100)
模型上的字段由用戶在注冊時完成。 為此,我按照這些說明編寫了一個自定義注冊表單類,它表明需要一個 signup() 方法:
# forms.py
class CustomSignupForm(SignupForm):
name = f.CharField(label=_("First Name"),
required=True,
widget=f.TextInput(attrs={'placeholder': _("First Name")})
)
dateOfBirth = f.DateField(label=_("Date of birth"),
required=True, initial='1990-01-01',
widget=f.DateInput()
)
city = f.CharField(label=_("City"),
required=True,
widget=f.TextInput(attrs={'placeholder': _("City")})
)
gender = f.ChoiceField(label=_("Gender"),
choices=GENDER_CHOICES,
required=True
)
def signup(self, request, user):
user.name = self.cleaned_data['name']
user.dateOfBirth = self.cleaned_data['dateOfBirth']
user.city = self.cleaned_data['city']
user.gender = self.cleaned_data['gender']
user.save()
return user
同樣的說明還告訴我我需要一個自定義的 allauth 適配器(這是基本的 allauth 適配器,但添加了諸如 dateOfBirth 和 city 之類的字段):
# adapter.py
class AccountAdapter(DefaultAccountAdapter):
def save_user(self, request, user, form, commit=False):
data = form.cleaned_data
user.email = data['email']
user.name = data['name']
user.dateOfBirth = data['dateOfBirth']
user.gender = data['gender']
user.city = data['city']
if 'password1' in data:
user.set_password(data['password1'])
else:
user.set_unusable_password()
self.populate_username(request, user)
if commit:
user.save()
return user
使用此設置,我不斷收到相同的錯誤(回溯):
禁止 save() 以防止由於未保存的相關對象“用戶”而導致數據丟失。
我在這里和這里找到了一個可能的解決方案,即將 save() 方法添加到自定義注冊表單:
# forms.py
class CustomSignupForm(SignupForm):
# ...
def save(self, user):
user.save()
當我嘗試這個時,我收到以下錯誤(回溯):
/accounts/signup/ 'WSGIRequest' 對象的 AttributeError 沒有屬性 'save'
我也嘗試過其他解決方案,例如this 。 如果有人能指出我正確的方向,我將不勝感激!
我的 django-allauth 的 settings.py 配置:
# settings.py (django-allauth)
ACCOUNT_ALLOW_REGISTRATION = env.bool("DJANGO_ACCOUNT_ALLOW_REGISTRATION", True)
ACCOUNT_AUTHENTICATION_METHOD = "email"
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
ACCOUNT_ADAPTER = "loteriai.users.adapters.AccountAdapter"
SOCIALACCOUNT_ADAPTER = "loteriai.users.adapters.SocialAccountAdapter"
ACCOUNT_FORMS = {'signup': 'loteriai.users.forms.CustomSignupForm'}
我正在使用以下軟件包:
Django Version: 3.1
Python Version: 3.8.3
django-allauth Version: 0.42.0
我設法解決了這個問題。 Django-Allauth 顯然在 User 模型中的自定義字段存在問題,而不是char fields 。
我的解決方案是使用單獨的User_Profile模型,該模型與 User 模型和所有必要的附加字段具有 OneToOne 關系:
# Models.py
class User_Profile(models.Model):
user = models.OneToOneField(User, verbose_name=_("user"),
related_name="profile",
on_delete=models.CASCADE)
tier = models.CharField(_("Plan"), choices=TIER_CHOICES,
default='FREE',
max_length=5)
dateOfBirth = models.DateField(_("Date of birth"),
auto_now=False,
auto_now_add=False,
null=True)
gender = models.CharField(_('Gender'), choices=GENDER_CHOICES,
default='MASC',
max_length=5,
null=True)
city = models.CharField(_("City"), max_length=100,
null=True)
確保您的字段沒有默認設置為null=True,因為這在下面的代碼流中很重要。
接下來,對於自定義表單,您需要保存方法而不是注冊方法。 我在這篇文章中發現了這一點。 顯然,注冊方法已被棄用。 有關官方文檔的更多信息。 我最終得到了以下 CustomSignupForm 類:
# forms.py
class CustomSignupForm(SignupForm):
name = f.CharField(label=_("First Name"),
required=True,
widget=f.TextInput(attrs={'placeholder': _("First Name")}))
dateOfBirth = f.DateField(label=_("Date of birth"), required=True,
initial='1990-01-01',
widget=f.DateInput())
city = f.CharField(label=_("City"),
required=True,
widget=f.TextInput(attrs={'placeholder': _("City")}))
gender = f.ChoiceField(label=_("Gender"), choices=GENDER_CHOICES, required=True)
def save(self, request):
user = super(CustomSignupForm, self).save(request)
user.name = self.cleaned_data['name']
user.save()
profile = user.profile
profile.dateOfBirth = self.cleaned_data['dateOfBirth']
profile.city = self.cleaned_data['city']
profile.gender = self.cleaned_data['gender']
profile.save()
return user
最后,每當創建/更新 User 模型時,您都需要創建一個信號來創建或更新配置文件模型:
# signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import User, User_Profile
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
User_Profile.objects.create(user=instance)
else:
try:
instance.profile.save()
except User.profile.RelatedObjectDoesNotExist:
# Run this when a profile in not found for a User instance
希望這有幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.