Django allauth如何保存自定义用户字段和注册表单。

4
我使用UserProfile模型扩展了标准用户模型,包含以下字段:
class UserProfile(models.Model):
    user = models.OneToOneField(User, related_name='profile')
    gender = models.CharField(max_length=30)
    info = models.CharField(max_length=30)

但是使用这个表单创建新用户时:
class SignupForm(forms.Form):
    first_name = forms.CharField(max_length=30, label='First name')
    last_name = forms.CharField(max_length=30, label='Last name')
    info = forms.CharField(max_length=30, label='info')
    def save(self, user):
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        profile = UserProfile()
        profile.user = user     
        profile.info = self.cleaned_data['info']
        profile.save()
        user.profile = profile
        user.save()

在数据库中,“info”始终为空(“”),其他字段也是如此,除了id。

标准属性(名字、姓氏)会被正确保存。

我尝试进行调试,发现错误与SQL无关,因为查询并没有问题:

INSERT INTO "user_profile" ("user_id", "info") VALUES (17, '',
 '') RETURNING "user_profile"."id";

然而,当我使用pdb调试user.profile.info的值时,它能够正常工作:

(Pdb) user.profile.info
u'info passed from form'

你的设置中是否有 ACCOUNT_SIGNUP_FORM_CLASS = 'your_app.forms.SignupForm' - illagrenan
是的,我会,抱歉忘了提到。 - George
我尝试过你的代码,self.cleaned_data['info'] 包含了我在表单中输入的数据(所以我认为你的问题与 django-allauth 无关)。也许你可以尝试如下语句: profile.info = u"some_test_data" - illagrenan
是的,那部分正确返回数据。我开始调整代码,然后在“user.profile = profile”行上出现了“无法设置属性”的错误,所以我将其删除,现在它可以工作了。我尝试了这个解决方案https://dev59.com/EHTYa4cB1Zd3GeqPum5N#17635831,但对我没有用。我不会将我的解决方案添加为已接受的答案,因为我不确定它是否正确。 - George
你能否尝试将 def save(self, user) 替换为 def signup(self, request, user) - andrea.ge
请查看Django allauth作者回答的这个问题:https://dev59.com/4Wct5IYBdhLWcg3wKqQd - Flimm
2个回答

2

首先,应该保存定制表单,但将提交设置为false,这样信息就不会立即进入数据库。之后,可以保存用户字段,然后可以设置一对一字段来链接两个表格,最后再进行保存。

class SignupForm(forms.Form):    
    def signup(self, user):
        profile = UserProfile()
        profile.save(commit = False)
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        user.save()
        user.profile = profile
        profile.user = user     
        profile.info = self.cleaned_data['info']
        profile.save()

顺便提一下,我们正在设置 profile.user 而不是 user.profile,这里的 profile 是从父类(User 类)继承而来的子类。


这看起来很粗糙。其他人建议子类化DefaultAccountAdapter。 - Brendan Metcalfe

-1

您正在覆盖错误的方法以保存用户信息。要覆盖的方法是signup而不是save

class SignupForm(forms.Form):
    ..........

    def signup(self, request, user):

        .....................

保存方法确实存在,但是注册也存在,不清楚应该在什么时候覆盖哪个方法。对答案进行更详细的说明肯定会有帮助,如果有的话我想投票支持这个答案。 - Divick
我看到在最新版本的allauth中,注册(signup)是拦截用户创建的方式,但似乎是在用户已经被持久化到数据库之后才被调用。为了能够在用户被持久化到数据库之前拦截用户创建表单,需要重写自定义AccountAdapter的save_user方法。 - Divick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接