如何在自定义用户模型中保存allauth自定义SignUp表单中的字段?

时间:2016-08-15 02:46:34

标签: django django-allauth

我有自定义用户

# custom_user/models.py

class MyUser(AbstractBaseUser, PermissionsMixin):
    USER_ACCOUNT_TYPE_CHOICES = (
        (1, _('organization')),
        (2, _('personal')),
    )

    user_account_type = models.IntegerField(_('account type'), choices=USER_ACCOUNT_TYPE_CHOICES)
    email = models.EmailField(_('email address'), max_length=255, unique=True)

USERNAME_FIELD = 'email'

class MyUserManager(BaseUserManager):
    def _create_user(self, email, password, username=None, **extra_fields):
        """
        Creates and saves a User with the given username, email and password.
        """
        if not email:
            raise ValueError('The given email must be set')
        email = self.normalize_email(email)
        if username:
            username = self.model.normalize_username(username)
            user = self.model(username=username, email=email, **extra_fields)
        else:
            user = self.model(email=email, **extra_fields)

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email=None, password=None, username=None, **extra_fields):
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, username=username, **extra_fields)

    def create_superuser(self, email, password, username=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff=True.')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')

        return self._create_user(email, password, username=username, **extra_fields)

在设置中,有用户User Model要使用的信息以及在用户注册时我需要在哪里找到其他字段。

# settings.py

ACCOUNT_SIGNUP_FORM_CLASS = 'custom_user.forms.SignupForm'
AUTH_USER_MODEL = 'custom_user.MyUser'

我发现很多主题都有不同的方法来配置allauth's SignupForm,但没有人工作。其中一种方法如下:

# custom_user/forms.py

from django.forms import ModelForm
from .models import MyUser

class SignupForm(ModelForm):
    class Meta:
        model = MyUser
        fields = ['user_account_type']

    def signup(self, request, user):
        user.user_account_type = self.cleaned_data['user_account_type']
        user.save()

在浏览器中,我看到2个选项(组织\个人)

请求信息 POST

Variable    Value
email      'test@gmail.com'
password2  'Test1234'
csrfmiddlewaretoken     'VvrW6PcR8G8OD3fDzunXbtDh4LdYiwzs5xxaYH4xvj'
password1   'Test1234'
user_account_type   '1'
username    'Test'

因此allauth会看到该字段,但无法将值保存在DB中。

实际错误是:

IntegrityError at /accounts/signup/
null value in column "user_account_type" violates not-null constraint

我的def signup是否正确?我还需要配置什么?

Django v1.10,allauth v0.26.1

已编辑:我找到了workaround

def signup(self, request, user):
    user_account_type = self.cleaned_data['user_account_type']         
    MyUser.objects.filter(email=user).update(user_account_type=user_account_type)

但在这种情况下,user_account_type还必须包含null=True, blank=True

应该更改哪些内容以避免此解决方法并一步保存所有注册信息(电子邮件,密码,帐户类型)?为什么allauth在保存电子邮件和密码时不会在同一个流程中保存user_account_type

1 个答案:

答案 0 :(得分:2)

目前,allauth在触发自定义注册方法之前已经保存了用户。因此,在您有机会插入user_account_type值之前,用户会被保存。

您可以使用自定义save_user适配器方法解决此问题:

class MyAccountAdapter(DefaultAccountAdapter):

    def save_user(self, request, user, form, commit=True):
        # Insert logic to inspect the signup form, or
        # put some default user values in here...
        user.user_account_type = form.cleaned_data['user_account_type']
        return super(MyAccountAdapter, self).save_user(
            request,
            user,
            form,
            commit)