I have django custom user model MyUser
with one extra field:
# 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-auth Signup 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:
IntegrityError at /accounts/signup/
(1048, "Column 'age' cannot be null")
What is the proper way to store Custom user model?
django-allauth: 0.12.0; django: 1.5.1; 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
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.
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.
So for anyone facing this issue, your CustomAdpater
would look like this
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
def save(self, request, user):
user.save() #save the user object first so you can use it for relationships
...
With Django 1.5 custom user model, the best practice is to use the get_user_model
function:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With