Cómo personalizar el perfil de usuario cuando se usa django-allauth

Tengo un proyecto django con la aplicación django-allauth. Necesito recostackr datos adicionales del usuario al registrarse. Me encontré con una pregunta similar aquí, pero desafortunadamente, nadie respondió la parte de personalización del perfil.

Según la documentación provista para django-allauth :

ACCOUNT_SIGNUP_FORM_CLASS (= None )

Una cadena que apunta a una clase de formulario personalizada (por ejemplo, 'myapp.forms.SignupForm' ) que se utiliza durante el registro para solicitar al usuario información adicional (por ejemplo, suscripción al boletín de noticias, fecha de nacimiento). Esta clase debe implementar un método 'save' , aceptando el usuario recién registrado como su único parámetro.

Soy nuevo en django y estoy luchando con esto. ¿Alguien puede dar un ejemplo de una clase de formulario personalizada? ¿Debo agregar también una clase de modelo con un enlace al objeto de usuario como este ?

Supongamos que desea preguntar al usuario su nombre / apellido durante el registro. Tendrá que poner estos campos en su propia forma, así:

 class SignupForm(forms.Form): first_name = forms.CharField(max_length=30, label='Voornaam') last_name = forms.CharField(max_length=30, label='Achternaam') def signup(self, request, user): user.first_name = self.cleaned_data['first_name'] user.last_name = self.cleaned_data['last_name'] user.save() 

Luego, en su configuración, apunte a esta forma:

 ACCOUNT_SIGNUP_FORM_CLASS = 'yourproject.yourapp.forms.SignupForm' 

Eso es todo.

Utilizando la solución sugerida por pennersr recibí una advertencia de depreciación:

 DeprecationWarning: The custom signup form must offer a def signup(self, request, user) method DeprecationWarning) 

Esto se debe a que a partir de la versión 0.15, el método de guardar ha quedado en desuso en favor de un método de suscripción def (solicitud, usuario).

Entonces para resolver esto, el código del ejemplo debería ser así:

 class SignupForm(forms.Form): first_name = forms.CharField(max_length=30, label='Voornaam') last_name = forms.CharField(max_length=30, label='Achternaam') def signup(self, request, user): user.first_name = self.cleaned_data['first_name'] user.last_name = self.cleaned_data['last_name'] user.save() 

Esto es lo que funcionó para mí combinando algunas de las otras respuestas (ninguna de ellas es 100% completa y SECA).

En yourapp/forms.py :

 from django.contrib.auth import get_user_model from django import forms class SignupForm(forms.ModelForm): class Meta: model = get_user_model() fields = ['first_name', 'last_name'] def signup(self, request, user): user.first_name = self.cleaned_data['first_name'] user.last_name = self.cleaned_data['last_name'] user.save() 

Y en settings.py :

 ACCOUNT_SIGNUP_FORM_CLASS = 'yourapp.forms.SignupForm' 

De esta forma, utiliza los formularios del modelo para que sea SECO y utiliza el nuevo def signup . Intenté poner 'myproject.myapp.forms.SignupForm' pero eso ocasionó un error de alguna manera.

En tus users/forms.py pones:

 from django.contrib.auth import get_user_model class SignupForm(forms.ModelForm): class Meta: model = get_user_model() fields = ['first_name', 'last_name'] def save(self, user): user.save() 

En settings.py pones:

 ACCOUNT_SIGNUP_FORM_CLASS = 'users.forms.SignupForm' 

De esta forma, no se rompe el principio DRY por multiplicidad Definición de campos de modelos de usuario.

@Shreyas: la solución a continuación puede no ser la más limpia, pero funciona. Por favor, avíseme si tiene alguna sugerencia para limpiarlo más.

Para agregar información que no pertenece al perfil de usuario predeterminado, primero cree un modelo en yourapp / models.py. Lea los documentos generales de django para obtener más información al respecto, pero básicamente:

 from django.db import models class UserProfile(models.Model): user = models.OneToOneField(User, related_name='profile') organisation = models.CharField(organisation, max_length=100, blank=True) 

Luego crea un formulario en yourapp / forms.py:

 from django import forms class SignupForm(forms.Form): first_name = forms.CharField(max_length=30, label='Voornaam') last_name = forms.CharField(max_length=30, label='Achternaam') organisation = forms.CharField(max_length=20, label='organisation') def signup(self, request, user): user.first_name = self.cleaned_data['first_name'] user.last_name = self.cleaned_data['last_name'] # Replace 'profile' below with the related_name on the OneToOneField linking back to the User model up = user.profile up.organisation = self.cleaned_data['organisation'] user.save() up.save() 

He probado muchos tutoriales diferentes y a todos les falta algo, repetir código innecesario o hacer cosas raras, a continuación sigue mi solución que reúne todas las opciones que he encontrado, está funcionando, ya lo he puesto en producción PERO Todavía no me convence porque esperaría recibir first_name y last_name dentro de las funciones que adjunté a Users create para evitar crear un perfil dentro del formulario, pero no pude, por el momento creo que te ayudará.

Models.py

 class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) bio = models.TextField(max_length=500, blank=True) nationality = models.CharField(max_length=2, choices=COUNTRIES) gender = models.CharField(max_length=1, choices=GENDERS) def __str__(self): return self.user.first_name @receiver(post_save, sender=User) def create_user_profile(sender, instance, created, **kwargs): if created: Profile.objects.create(user=instance) @receiver(post_save, sender=User) def save_user_profile(sender, instance, **kwargs): instance.profile.save() 

Forms.py

 class SignupForm(forms.ModelForm): first_name = forms.CharField(max_length=100) last_name = forms.CharField(max_length=100) class Meta: model = Profile fields = ('first_name', 'last_name', 'nationality', 'gender') def signup(self, request, user): # Save your user user.first_name = self.cleaned_data['first_name'] user.last_name = self.cleaned_data['last_name'] user.save() user.profile.nationality = self.cleaned_data['nationality'] user.profile.gender = self.cleaned_data['gender'] user.profile.save() 

Settings.py

 ACCOUNT_SIGNUP_FORM_CLASS = 'apps.profile.forms.SignupForm' 

Crear un modelo de perfil con el usuario como OneToOneField

 class Profile(models.Model): user = models.OneToOneField(User, verbose_name=_('user'), related_name='profiles') first_name=models.CharField(_("First Name"), max_length=150) last_name=models.CharField(_("Last Name"), max_length=150) mugshot = ImageField(_('mugshot'), upload_to = upload_to, blank=True) phone= models.CharField(_("Phone Number"), max_length=100) security_question = models.ForeignKey(SecurityQuestion, related_name='security_question') answer=models.CharField(_("Answer"), max_length=200) recovery_number= models.CharField(_("Recovery Mobile Number"), max_length=100) city=models.ForeignKey(City,related_name='city', blank=True, null=True, help_text=_('Select your City')) location=models.ForeignKey(Country,related_name='location', blank=True, null=True, help_text=_('Select your Location'))