web-dev-qa-db-fra.com

Comment personnaliser le profil utilisateur lors de l'utilisation de Django-allauth

J'ai un projet Django avec l'application Django-allauth. J'ai besoin de collecter des données supplémentaires auprès de l'utilisateur lors de l'inscription. J'ai rencontré un problème similaire question ici mais malheureusement, personne n'a répondu à la partie de personnalisation du profil.

Per la documentation fournie pour Django-allauth :

ACCOUNT_SIGNUP_FORM_CLASS (= None)

Une chaîne pointant vers une classe de formulaire personnalisée (par exemple, ‘myapp.forms.SignupForm’) utilisé lors de l'inscription pour demander à l'utilisateur d'autres entrées (par exemple, inscription à un bulletin d'information, date de naissance). Cette classe devrait implémenter un ‘save’ méthode, en acceptant le nouvel utilisateur comme seul paramètre.

Je suis nouveau sur Django et je lutte contre cela. Quelqu'un peut-il fournir un exemple d'une classe de formulaire personnalisée? Dois-je également ajouter une classe de modèle avec un lien vers l'objet utilisateur, comme ceci ?

98
Shreyas

Supposons que vous souhaitiez demander à l'utilisateur son nom/prénom lors de l'inscription. Vous aurez besoin de mettre ces champs dans votre propre formulaire, comme suit:

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

Ensuite, dans vos paramètres, pointez sur ce formulaire:

ACCOUNT_SIGNUP_FORM_CLASS = 'yourproject.yourapp.forms.SignupForm'

C'est tout.

156
pennersr

En utilisant la solution proposée par pennersr, je recevais un message DeprecationWarning:

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

En effet, à partir de la version 0.15 la méthode de sauvegarde est devenue obsolète au profit d’une méthode d’inscription def (demande, utilisateur).

Donc pour résoudre ceci, le code de l'exemple devrait être comme ceci:

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

Voici ce qui a fonctionné pour moi en combinant quelques-unes des autres réponses (aucune d’entre elles n’est complète à 100% et sèche).

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

Et en settings.py:

ACCOUNT_SIGNUP_FORM_CLASS = 'yourapp.forms.SignupForm'

De cette façon, il utilise les formulaires de modèle de manière à ce qu'il soit sec et utilise le nouveau def signup. J'ai essayé de mettre 'myproject.myapp.forms.SignupForm' _ mais cela a entraîné une erreur en quelque sorte.

15
Howardwlo

@Shreyas: La solution ci-dessous n'est peut-être pas la plus propre, mais ça fonctionne. S'il vous plaît laissez-moi savoir si vous avez des suggestions pour le nettoyer plus loin.

Pour ajouter des informations qui n'appartiennent pas au profil utilisateur par défaut, créez d'abord un modèle dans votreapp/models.py. Lisez la documentation générale Django pour en savoir plus, mais en gros:

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)

Ensuite, créez un formulaire dans 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()
5
mark

Dans votre users/forms.py tu mets:

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

Dans settings.py vous mettez:

ACCOUNT_SIGNUP_FORM_CLASS = 'users.forms.SignupForm'

De cette manière, vous ne diviserez pas DRY principe par multiplicité) la définition des champs de modèles utilisateur.

4
Adam Dobrawy

J'ai essayé beaucoup de tutoriels différents et il manque à tous quelque chose, répétant du code inutile ou faisant des choses bizarres, voici une solution qui regroupe toutes les options que j'ai trouvées, ça marche, je l'ai déjà mis en production MAIS ça Je ne suis toujours pas convaincu parce que je m'attendrais à recevoir les prénoms et noms dans les fonctions que j'ai attachées aux utilisateurs afin d'éviter de créer un profil dans le formulaire, mais je ne pouvais pas, mais je pense que cela vous aidera.

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

Paramètres.py

ACCOUNT_SIGNUP_FORM_CLASS = 'apps.profile.forms.SignupForm'
4
Gregory