簡體   English   中英

Django-Allauth - 自定義用戶模型和自定義注冊表單的錯誤

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM