Reputation: 5094
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?
Upvotes: 0
Views: 344
Reputation: 6521
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)
Upvotes: 2