7

我有一个带有一个额外字段的 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"

我还根据这些说明自定义了所有身份验证注册表单类

# 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正确呈现),我收到此错误:

/accounts/signup/ 处的 IntegrityError
(1048,“列‘年龄’不能为空”)

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

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

4

3 回答 3

13

虽然有点晚了,但万一它对某人有帮助。

您需要通过继承 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 来在用户注册期间创建其他模型,并且您需要进行一个原子事务,以防止任何数据保存到数据库,除非它们都成功。

DefaultAdapterfor django-allauth 可以保存用户,因此如果您的自定义 SignupForm 方法出现错误,用户save仍将被持久保存到数据库中。

所以对于任何面临这个问题的人来说,你CustomAdpater会看起来像这样

类用户帐户适配器(默认帐户适配器):

    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
    ...
于 2016-08-27T10:36:46.427 回答
1

边注

使用 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'

也许它不相关,但我认为这将是值得注意的。

于 2013-07-14T01:46:07.457 回答
0

i think you should define fields property in class Meta in SignupForm and set list of fields that contains age, like this :

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

and if it's not worked, look at this

于 2015-10-13T09:26:01.150 回答