Résolue

User et superuser dans le même modèle

# Bases de données # Django # Documentation

Bonjour, je souhaite dans mon application définir des utilisateurs avec email comme identifiant de connexion et des champs obligatoires nom, prenom et adresse.
Dasn le même temps je ne souhaite utiliser qu'un email, nom et prenom (pas d'adresse) pour le superuser. J'ai donc différencié les fonctions create_user et create_superuser.
Est-ce la bonne façon de procéder? fFaut-il lier un profil pour différencier user et superuser?

D'autre part la doc Django indique qu'un champ qui a blank=False doit apparaitre dans REQUIRED_FIELDS, or je ne veux pas que ces champs me soient demandés avec la commande manage.py createsuperuser.
J'ai donc essayé sans inclure le champ adresse et cela semble fonctionner quand même.

Voici les modèles CustomManager et CustomUser que j'ai créé, avec les champs obligatoire qui ont blank=False:

class CustomManager(BaseUserManager):  # on crée un manager qui va gérer notre modèle Visiteur customisé
    def create_user(self, email='', nom='', prenom='', adresse='', password=None):  
        if not email:
            raise ValueError("Vous devez entrer un email.")

        # On utilise l'attribut 'model' du manager. Cet attribut fait référence au modèle géré par le manager (CustomUser)
        user = self.model(
            email=self.normalize_email(email),
            nom=nom,
            prenom=prenom,
            adresse=adresse,
        )
        user.set_password(password)
        user.save()
        return user

    def create_superuser(self, email,  nom='', prenom='', password=None):
        if not email:
            raise ValueError("Vous devez entrer un email.")

        # On utilise l'attribut 'model' du manager. Cet attribut fait référence au modèle géré par le manager (CustomUser)
        user = self.model(
            email=self.normalize_email(email),
            nom=nom,
            prenom=prenom
        )
        user.set_password(password)
        # user = self.create_user(email=email, nom=nom, prenom=prenom, password=password)
        user.is_admin = True
        user.is_staff = True
        user.save()
        return user


class CustomUser(AbstractBaseUser):  

    nom = models.CharField(max_length=150, blank=False)
    prenom = models.CharField(max_length=150, blank=False)
    adresse = models.CharField(max_length=150, blank=False)
    email = models.EmailField(max_length=150, unique=True, blank=False)
    is_active = models.BooleanField(default=True) 
    is_staff = models.BooleanField(default=False)  
    is_admin = models.BooleanField(default=False)  

    USERNAME_FIELD = "email"  # on indique le champ qui servira d'id de connexion
    REQUIRED_FIELDS = ["nom", "prenom"]  # on n'inclut pas le champ qui sert de 'username'

    objects = CustomManager()  

    def has_perm(self, perm, obj=None):
        return True

    def has_module_perms(self, app_label):
        return True

Merci pour votre aide.
Ali

Salut Ali !

Différencier les fonctions create_user et create_superuser est une bonne méthode pour créer des superutilisateurs sans exiger tous les champs.

La raison pour laquelle ça fonctionne sans que tu aies besoin de mettre adresse dans le REQUIRED_FIELDS est que la commande createsuperuser ne requiert que les champs spécifiés dans REQUIRED_FIELDS en plus du champ défini par USERNAME_FIELD et password.

Comme tu as séparé la création de l’utilisateur standard et du superutilisateur, cette méthode te permet de contourner l'exigence d'adresse pour le superutilisateur.

Pour moi c'est pas nécessaire de lier un profil pour différencier user et superuser car les champs is_staff et is_admin dans ton modèle CustomUser permettent déjà cette distinction au niveau de l'authentification et des permissions dans Django.

Ton modèle CustomUser hérite bien de AbstractBaseUser, ce qui est correct pour une personnalisation avancée.

Bref ça m'a l'air correcte.

Salut Pacdev, merci pour ta réponse.
Pour cette recommandation Django "D'autre part la doc Django indique qu'un champ qui a blank=Falsedoit apparaitre dans REQUIRED_FIELDS" on n'est donc pas obligé d'inclure un champ qu'on a marqué comme non vide dans REQUIRED_FIELDS" ?

Salut Ali,

L'attribut blank=False dans un modèle de Django indique que le champ doit être rempli lors de la soumission d'un formulaire. Ce n'est pas lié directement à la création d'un superutilisateur via la ligne de commande, mais plutôt à la validation de formulaires au sein de l'application web elle-même.

même si tu as adresse = models.CharField(max_length=150, blank=False) dans ton modèle, ça veut dire que le champ adresse ne peut pas être vide lorsqu'un formulaire est soumis dans le cadre normal de fonctionnement de ton application.

Je pense que la confusion vient du fait que, en général, si un champ est requis dans le modèle (i.e., blank=False), tu voudrais également le rendre requis lors de la création d'un utilisateur ou superutilisateur pour maintenir de la cohérence. Cependant, Django permet une certaine flexibilité avec la commande createsuperuser, permettant de ne pas inclure certains champs dans REQUIRED_FIELDS si tu choisis de les rendre non-obligatoires lors de cette procédure particulière.

Pour résumer, pour createsuperuser, tu n'es effectivement pas obligé d'inclure tous les champs blank=False dans REQUIRED_FIELDS.

J'en discuterai avec Thibault pour être sûr mais pour moi c'est la nuance.

superbe Pacdev, c'est limpide. Dans mon cas cela a fonctionné mais c'est toujours meiux de se le faire expliquer par les pros ;-)

Inscris-toi

(c'est gratuit !)

Inscris-toi

Tu dois créer un compte pour participer aux discussions.

Créer un compte

Rechercher sur le site

Formulaire de contact

Inscris-toi à Docstring

Pour commencer ton apprentissage.

Tu as déjà un compte ? Connecte-toi.