简体   繁体   English

使用 django-allauth 保存自定义用户模型

[英]Saving custom user model with django-allauth

I have django custom user model MyUser with one extra field:我有 django 自定义用户模型MyUser一个额外的字段:

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

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

# settings.py
AUTH_USER_MODEL = "web.MyUser"

I also have according to these instructions custom all-authSignup 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'

After submitting SignupForm (field for property MyUser.age is rendered corectly), I get this error:提交SignupForm (属性MyUser.age的字段正确呈现)后,我收到此错误:

IntegrityError at /accounts/signup/ /accounts/signup/ 处的 IntegrityError
(1048, "Column 'age' cannot be null") (1048,“列‘年龄’不能为空”)

What is the proper way to store Custom user model?存储自定义用户模型的正确方法是什么?

django-allauth: 0.12.0; django-allauth:0.12.0; django: 1.5.1; django:1.5.1; Python 2.7.2 Python 2.7.2

Though it is a bit late but in case it helps someone.虽然有点晚了,但万一它对某人有帮助。

You need to create your own Custom AccountAdapter by subclassing DefaultAccountAdapter and setting the您需要通过继承 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()

and you also need to define the following in settings:您还需要在设置中定义以下内容:

ACCOUNT_ADAPTER = 'api.adapter.UserAccountAdapter'

This is also useful, if you have a custom SignupForm to create other models during user registration and you need to make an atomic transaction that would prevent any data from saving to the database unless all of them succeed.这也很有用,如果您有一个自定义的 SignupForm 来在用户注册期间创建其他模型,并且您需要进行一个原子事务,以防止任何数据保存到数据库,除非它们都成功。

The DefaultAdapter for django-allauth saves the user, so if you have an error in the save method of your custom SignupForm the user would still be persisted to the database. django-allauth 的DefaultAdapter保存用户,因此如果您的自定义 SignupForm 的save方法有错误,用户仍将被持久保存到数据库中。

So for anyone facing this issue, your CustomAdpater would look like this因此,对于面临此问题的任何人,您的CustomAdpater将如下所示

class 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

Then you can decorate your custom SignupForm's with @transaction.atomic然后你可以用@transaction.atomic装饰你的自定义注册表格

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

Side note边注

With Django 1.5 custom user model, the best practice is to use the get_user_model function:对于 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'

Maybe it's not related, but I thought it would be worth noticing.也许它不相关,但我认为这将是值得注意的。

i think you should define fields property in class Meta in SignupForm and set list of fields that contains age, like this :我认为您应该在 SignupForm 的 Meta 类中定义字段属性,并设置包含年龄的字段列表,如下所示:

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

and if it's not worked, look at this如果它不起作用,看看这个

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM