用Django allauth保存自定义用户模型

2024-09-27 07:20:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我有djangocustom user modelMyUser和一个额外字段:

# models.py
from django.contrib.auth.models import AbstractUser

class MyUser(AbstractUser):
    age = models.PositiveIntegerField(_("age"))

# settings.py
AUTH_USER_MODEL = "web.MyUser"

我还有根据to these instructions自定义的所有身份验证Signup form class

# forms.py
class SignupForm(forms.Form):
    first_name = forms.CharField(max_length=30)
    last_name = forms.CharField(max_length=30)
    age = forms.IntegerField(max_value=100)

    class Meta:
        model = MyUser

    def save(self, user):
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        user.age = self.cleaned_data['age']
        user.save()

# settings.py
ACCOUNT_SIGNUP_FORM_CLASS = 'web.forms.SignupForm'

提交SignupForm(属性MyUser.age的字段被核心呈现)后,我得到以下错误:

IntegrityError at /accounts/signup/
(1048, "Column 'age' cannot be null")

存储自定义用户模型的正确方法是什么?

django allauth:0.12.0;django:1.5.1;Python 2.7.2


Tags: djangonamepyselfagemodelsformsmax
3条回答

虽然有点晚了,但万一能帮上忙。

您需要通过子类化DefaultAccountAdapter并设置

class UserAccountAdapter(DefaultAccountAdapter):

    def save_user(self, request, user, form, commit=True):
        """
        This is called when saving user via allauth registration.
        We override this to set additional data on user object.
        """
        # Do not persist the user yet so we pass commit=False
        # (last argument)
        user = super(UserAccountAdapter, self).save_user(request, user, form, commit=False)
        user.age = form.cleaned_data.get('age')
        user.save()

您还需要在“设置”中定义以下内容:

ACCOUNT_ADAPTER = 'api.adapter.UserAccountAdapter'

如果在用户注册期间有一个自定义的SignupForm来创建其他模型,并且需要生成一个原子事务,该事务将阻止任何数据保存到数据库,除非所有数据都成功。

django allauth的DefaultAdapter保存用户,因此,如果自定义注册表单的save方法中有错误,则用户仍将被持久化到数据库中。

因此,对于任何面临此问题的人,您的CustomAdpater将如下所示

类UserAccountAdapter(DefaultAccountAdapter):

    def save_user(self, request, user, form, commit=False):
        """
        This is called when saving user via allauth registration.
        We override this to set additional data on user object.
        """
        # Do not persist the user yet so we pass commit=False
        # (last argument)
        user = super(UserAccountAdapter, self).save_user(request, user, form, commit=commit)
        user.age = form.cleaned_data.get('age')
        # user.save() This would be called later in your custom SignupForm

然后您可以用@transaction.atomic装饰您的自定义注册表单

@transaction.atomic
def save(self, request, user):
    user.save() #save the user object first so you can use it for relationships
    ...

我认为您应该在SignupForm的类Meta中定义fields属性,并设置包含age的字段列表,如下所示:

class SignupForm(forms.Form):
...
   class Meta:
      model = MyUser
      fields = ['first_name', 'last_name', 'age']

如果不起作用,看看 this

旁注

对于Django 1.5自定义用户模型,最佳实践是使用get_user_model函数:

from django.contrib.auth import get_user_model

# forms.py
class SignupForm(forms.Form):
    first_name = forms.CharField(max_length=30)
    last_name = forms.CharField(max_length=30)
    age = forms.IntegerField(max_value=100)

    class Meta:
        model = get_user_model() # use this function for swapping user model

    def save(self, user):
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        user.age = self.cleaned_data['age']
        user.save()

# settings.py
ACCOUNT_SIGNUP_FORM_CLASS = 'web.forms.SignupForm'

也许没有关系,但我觉得值得注意。

相关问题 更多 >

    热门问题