Como personalizar o perfil do usuário ao usar o django-allauth

Eu tenho um projeto de django com o aplicativo django-allauth. Eu preciso coletar dados adicionais do usuário na inscrição. Eu me deparei com uma pergunta semelhante aqui, mas, infelizmente, ninguém respondeu à parte de personalização do perfil.

De acordo com a documentação fornecida para o django-allauth :

ACCOUNT_SIGNUP_FORM_CLASS (= None )

Uma string apontando para uma class de formulário personalizada (por exemplo, 'myapp.forms.SignupForm' ) que é usada durante a inscrição para solicitar ao usuário informações adicionais (por exemplo, inscrição no boletim informativo, data de nascimento). Esta class deve implementar um método 'save' , aceitando o usuário recém-cadastrado como seu único parâmetro.

Eu sou novo no Django e estou lutando com isso. Alguém pode fornecer um exemplo de tal class de formulário personalizada? Eu preciso adicionar uma class de modelo, bem como um link para o object de usuário como este ?

Suponha que você queira perguntar ao usuário seu primeiro / último nome durante a inscrição. Você precisará colocar esses campos em seu próprio formulário, assim:

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

Em seguida, nas suas configurações, aponte para este formulário:

 ACCOUNT_SIGNUP_FORM_CLASS = 'yourproject.yourapp.forms.SignupForm' 

Isso é tudo.

Usando a solução sugerida pelo pennersr eu estava recebendo uma DeprecationWarning:

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

Isso ocorre porque, a partir da versão 0.15, o método de salvaguarda foi preterido em favor de um método de inscrição (solicitação, usuário) def.

Então, para resolver isso, o código do exemplo deve ser assim:

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

Aqui está o que funcionou para mim combinando algumas das outras respostas (nenhuma delas é 100% completa e seca).

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

E em settings.py :

 ACCOUNT_SIGNUP_FORM_CLASS = 'yourapp.forms.SignupForm' 

Dessa forma, ele usa os formulários de modelo para que seja DRY e use a nova def signup . Eu tentei colocar 'myproject.myapp.forms.SignupForm' mas isso resultou em um erro de alguma forma.

Em seus users/forms.py você coloca:

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

Em settings.py você coloca:

 ACCOUNT_SIGNUP_FORM_CLASS = 'users.forms.SignupForm' 

Desta forma, você não quebra o princípio DRY pela multiplicidade de definição de campos de modelos do usuário.

@Shreyas: A solução abaixo pode não ser a mais limpa, mas funciona. Por favor, deixe-me saber se você tem alguma sugestão para limpá-lo ainda mais.

Para adicionar informações que não pertencem ao perfil de usuário padrão, primeiro crie um modelo em yourapp / models.py. Leia os documentos gerais do django para aprender mais sobre isso, mas basicamente:

 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) 

Em seguida, crie um formulário em 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() 

Eu tentei muitos tutoriais diferentes e todos eles estão faltando alguma coisa, repetindo código desnecessário ou fazendo coisas estranhas, abaixo segue minha solução que une todas as opções que eu encontrei, está funcionando, eu já coloquei em produção, mas ainda não me convencendo porque eu esperaria receber first_name e last_name dentro das funções que eu anexei para Users criar para evitar criar um perfil dentro do formulário mas eu não pude, pelo menos acho que ele irá te ajudar.

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' 

Criar um modelo de perfil com usuário 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'))