Guardando modelo de usuario personalizado con django-allauth

Tengo el modelo de usuario personalizado django MyUser con un campo adicional:

 # models.py from django.contrib.auth.models import AbstractUser class MyUser(AbstractUser): age = models.PositiveIntegerField(_("age")) # settings.py AUTH_USER_MODEL = "web.MyUser" 

También tengo, de acuerdo con estas instrucciones, clase de formulario de registro personalizado :

 # 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' 

Después de enviar el SignupForm (el campo de la propiedad MyUser.age se procesa correctamente), aparece este error:

IntegrityError en / accounts / signup /
(1048, “la columna ‘age’ no puede ser nula”)

¿Cuál es la forma correcta de almacenar el modelo de usuario personalizado?

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

Aunque es un poco tarde pero por si acaso ayuda a alguien.

Debe crear su propio Custom AccountAdapter subclasificando DefaultAccountAdapter y configurando el

 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() 

y también necesitas definir lo siguiente en la configuración:

 ACCOUNT_ADAPTER = 'api.adapter.UserAccountAdapter' 

Esto también es útil, si tiene un Formulario de registro personalizado para crear otros modelos durante el registro del usuario y necesita realizar una transacción atómica que impida que cualquier dato se guarde en la base de datos a menos que todos tengan éxito.

El DefaultAdapter para django-allauth guarda al usuario, por lo que si tiene un error en el método de save de su formulario de registro personalizado, el usuario continuará en la base de datos.

Así que para cualquier persona que se enfrenta a este problema, su CustomAdpater se vería así

clase 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 

Luego puede decorar sus formularios personalizados con @transaction.atomic

 @transaction.atomic def save(self, request, user): user.save() #save the user object first so you can use it for relationships ... 

Nota al margen

Con el modelo de usuario personalizado Django 1.5, la mejor práctica es usar la función 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' 

Tal vez no esté relacionado, pero pensé que valdría la pena darse cuenta.

Creo que deberías definir la propiedad de los campos en la clase Meta en el formulario de registro y establecer una lista de campos que contenga la edad, como esto:

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

Y si no funciona, mira esto.