I have custom user
# 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)
In the settings there is info which User Model
to use and where to find additional field I need when user signing up.
# settings.py
ACCOUNT_SIGNUP_FORM_CLASS = 'custom_user.forms.SignupForm'
AUTH_USER_MODEL = 'custom_user.MyUser'
I found a lot of topics with different methods to configure allauth's SignupForm
, but no one works. One of the method is below:
# 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()
In a browser I see 2 choices (organization\personal)
Request information POST
Variable Value
email '[email protected]'
password2 'Test1234'
csrfmiddlewaretoken 'VvrW6PcR8G8OD3fDzunXbtDh4LdYiwzs5xxaYH4xvj'
password1 'Test1234'
user_account_type '1'
username 'Test'
so allauth sees the field but can not save the value in DB.
The actual error is:
IntegrityError at /accounts/signup/
null value in column "user_account_type" violates not-null constraint
Is my def signup
correct? What else do I need to configure?
Django v1.10, allauth v0.26.1
EDITED: I found the 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)
but in this case user_account_type
must also include null=True, blank=True
What should be changed to avoid this workaround and save all information of registration (email, password, account type) in one step? Why allauth
does not save user_account_type
in the same flow when saves email and password?
Currently, allauth
already saves the user before triggering your custom signup method. So, the user gets saved before you get the chance to plug in the user_account_type
value.
You can work around this by using a custom save_user
adapter method:
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)