Django Allauth 注册表单不保存自定义字段

Django Allauth signup form not saving custom fields

我正在尝试做一些应该非常简单的事情:添加一个注册字段并将其保存到我的用户对象中。我正在使用 allauth,所以据我所知,应该通过修改 allauth 表单进行注册。我已按照此处的说明进行操作:How to customize user profile when using django-allauth:

这是我的 forms.py 的样子:

from allauth.account.forms import SignupForm
from django import forms

UNASSIGNED = 'NA'
CLIENT = 'CL'
USER_TYPE_CHOICES = (
    (UNASSIGNED, 'Unassigned'),
    (CLIENT, 'Client'),
)

class CustomSignupForm(SignupForm):
    user_type = forms.CharField( 
        widget=forms.Select(choices=USER_TYPE_CHOICES))
    def signup(self, request, user):
        user.user_type = self.cleaned_data['user_type']
        user.save
        return user

然后是我的自定义用户:

class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(max_length=254, unique=True)
    name = models.CharField(max_length=254, null=True, blank=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    last_login = models.DateTimeField(null=True, blank=True)
    date_joined = models.DateTimeField(auto_now_add=True)
    
    UNASSIGNED = 'NA'
    CLIENT = 'CL'
    USER_TYPE_CHOICES = (
        (UNASSIGNED, 'Unassigned'),
        (CLIENT, 'Client'),
    )
    user_type = models.CharField(max_length=2,
                                      choices=USER_TYPE_CHOICES,
                                      default=UNASSIGNED)

    USERNAME_FIELD = 'email'
    EMAIL_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = UserManager()

    def get_absolute_url(self):
        return "/users/%i/" % (self.pk)

我知道我添加到用户的字段是有效的,我可以在管理员中看到它并在 shell 中访问它。表单正确呈现(我可以看到新字段的下拉列表。)问题是表单从不保存新的 user_type 字段,它总是显示为未分配。我将不胜感激有关故障排除的任何建议!我已经研究了一段时间,但没有发现任何有相同问题的讨论帖。

好的,在尝试了许多不同的已发布解决方案之后,我发现了一些可行的方法。我不确定为什么,所以如果有人知道,我会喜欢一个解释,但我将其张贴在这里以防其他人遇到类似的问题并且只是想要解决方案。

这是我最终的注册表单的样子:

class CustomSignupForm(SignupForm):
    user_type = forms.CharField( 
        widget=forms.Select(choices=USER_TYPE_CHOICES))

    class Meta:
        model = User

    def save(self, request):
        user = super(CustomSignupForm, self).save(request)
        user.user_type = self.cleaned_data['user_type']
        user.save()
        return user

而不是包含 signup() 函数,看起来您需要使用 def save(self, request): 作为注册(我认为)已弃用。然后你需要添加 user = super(MyCustomSignupForm, self).save(request) 文档中提到的 here. 那是我真的不明白的部分,但就是这样。如果我想通了,我会尽量记得回来编辑它。

当我开始使用 Allauth 时,我确实遇到了同样的挑战。主要区别是 Allauth 使用 DefaultAccountAdapter to handle the save_user logic. This is where super comes in. As mentioned in this SO post 你在使用 super 时调用父级的保存函数和你自己的保存函数。当不在这里调用 super 时,自定义字段永远不会传递到适配器中。尝试通过编写您自己的自定义适配器来发现 DefaultaccountAdapter:

custom_adapter.py

class CustomAccountAdapter(DefaultAccountAdapter): 
     # your custom logic 
     return user #or whatever your user model is called 

别忘了将其放入您的设置中:

ACCOUNT_ADAPTER = 'yourappname.custom_adapter.CustomAccountAdapter'

编码愉快!