Question

Quelle est la meilleure façon d'étendre le modèle User (fourni avec l'application d'authentification de Django) avec des champs personnalisés ?J'aimerais également éventuellement utiliser l'e-mail comme nom d'utilisateur (à des fins d'authentification).

j'ai déjà vu un peu façons pour le faire, mais je n'arrive pas à décider lequel est le meilleur.

Était-ce utile?

La solution

La manière la moins pénible et en fait recommandée par Django de procéder consiste à utiliser un OneToOneField(User) propriété.

Extension du modèle utilisateur existant

Si vous souhaitez stocker des informations relatives à User, vous pouvez utiliser un relation individuelle à un modèle contenant les champs pour des informations supplémentaires.Ce modèle individuel est souvent appelé modèle de profil, car il peut stocker des informations non liées à l'authentification sur un utilisateur du site.

Cela dit, étendre django.contrib.auth.models.User et le supplanter fonctionne aussi...

Remplacement d'un modèle utilisateur personnalisé

Certains types de projets peuvent avoir des exigences d'authentification pour lesquelles le logiciel intégré de Django User Le modèle n’est pas toujours approprié.Par exemple, sur certains sites, il est plus logique d’utiliser une adresse e-mail comme jeton d’identification plutôt qu’un nom d’utilisateur.

[Éd. : Deux avertissements et une notification suivent, mentionnant qu'il s'agit assez drastique.]

J'éviterais certainement de modifier la classe User réelle dans votre arborescence source Django et/ou de copier et de modifier le module d'authentification.

Autres conseils

Note:cette réponse est obsolète.voir d'autres réponses si vous utilisez Django 1.7 ou version ultérieure.

C'est comme ça que je procède.

#in models.py
from django.contrib.auth.models import User
from django.db.models.signals import post_save

class UserProfile(models.Model):  
    user = models.OneToOneField(User)  
    #other fields here

    def __str__(self):  
          return "%s's profile" % self.user  

def create_user_profile(sender, instance, created, **kwargs):  
    if created:  
       profile, created = UserProfile.objects.get_or_create(user=instance)  

post_save.connect(create_user_profile, sender=User) 

#in settings.py
AUTH_PROFILE_MODULE = 'YOURAPP.UserProfile'

Cela créera un profil utilisateur chaque fois qu'un utilisateur est enregistré s'il est créé.Vous pouvez alors utiliser

  user.get_profile().whatever

Voici quelques informations supplémentaires provenant de la documentation

http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users

Mise à jour: Veuillez noter que AUTH_PROFILE_MODULE est obsolète depuis la v1.5 : https://docs.djangoproject.com/en/1.5/ref/settings/#auth-profile-module

Eh bien, du temps s'est écoulé depuis 2008 et il est temps d'apporter une nouvelle réponse.Depuis Django 1.5, vous pourrez créer une classe User personnalisée.En fait, au moment où j'écris ceci, il est déjà fusionné dans master, vous pouvez donc l'essayer.

Il y a des informations à ce sujet dans documents ou si vous voulez approfondir la question, dans cet engagement.

Il ne vous reste plus qu'à ajouter AUTH_USER_MODEL aux paramètres avec le chemin d'accès à la classe d'utilisateurs personnalisée, qui s'étend soit AbstractBaseUser (version plus personnalisable) ou AbstractUser (classe User plus ou moins ancienne que vous pouvez étendre).

Pour les personnes qui ont la flemme de cliquer, voici un exemple de code (tiré de documents):

from django.db import models
from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser
)


class MyUserManager(BaseUserManager):
    def create_user(self, email, date_of_birth, password=None):
        """
        Creates and saves a User with the given email, date of
        birth and password.
        """
        if not email:
            raise ValueError('Users must have an email address')

        user = self.model(
            email=MyUserManager.normalize_email(email),
            date_of_birth=date_of_birth,
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, username, date_of_birth, password):
        """
        Creates and saves a superuser with the given email, date of
        birth and password.
        """
        u = self.create_user(username,
                        password=password,
                        date_of_birth=date_of_birth
                    )
        u.is_admin = True
        u.save(using=self._db)
        return u


class MyUser(AbstractBaseUser):
    email = models.EmailField(
                        verbose_name='email address',
                        max_length=255,
                        unique=True,
                    )
    date_of_birth = models.DateField()
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = MyUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['date_of_birth']

    def get_full_name(self):
        # The user is identified by their email address
        return self.email

    def get_short_name(self):
        # The user is identified by their email address
        return self.email

    def __unicode__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True

    @property
    def is_staff(self):
        "Is the user a member of staff?"
        # Simplest possible answer: All admins are staff
        return self.is_admin

Depuis Django 1.5, vous pouvez facilement étendre le modèle utilisateur et conserver une seule table dans la base de données.

from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils.translation import ugettext_lazy as _

class UserProfile(AbstractUser):
    age = models.PositiveIntegerField(_("age"))

Vous devez également le configurer comme classe d'utilisateurs actuelle dans votre fichier de paramètres

# supposing you put it in apps/profiles/models.py
AUTH_USER_MODEL = "profiles.UserProfile"

Si vous souhaitez ajouter de nombreuses préférences d'utilisateurs, l'option OneToOneField peut être un meilleur choix.

Une note pour les personnes développant des bibliothèques tierces :si vous avez besoin d'accéder à la classe d'utilisateurs, n'oubliez pas que les utilisateurs peuvent la modifier.Utilisez l'assistant officiel pour obtenir la bonne classe

from django.contrib.auth import get_user_model

User = get_user_model()

Il existe une recommandation officielle sur stocker des informations supplémentaires sur les utilisateurs.Le Django Book aborde également ce problème dans la section Profils.

Celle ci-dessous est une autre approche pour étendre un utilisateur.Je pense que c'est plus clair, facile et lisible qu'au-dessus de deux approches.

http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/

En utilisant l'approche ci-dessus :

  1. tu n'as pas besoin d'utiliseruser.get_profile().newattribute Pour accéder aux informations supplémentaires liées à l'utilisateur
  2. Vous pouvez simplement accéder directement à de nouveaux attributs supplémentaires viautilisateur.nouvelattribut

Vous pouvez simplement étendre le profil utilisateur en créant une nouvelle entrée à chaque fois que l'utilisateur est créé à l'aide des signaux de sauvegarde post-Django.

modèles.py

from django.db.models.signals import *
from __future__ import unicode_literals

class userProfile(models.Model):

    userName = models.OneToOneField(User, related_name='profile')
    city = models.CharField(max_length=100, null=True)

    def __unicode__(self):  # __str__
        return unicode(self.userName)

def create_user_profile(sender, instance, created, **kwargs):
    if created:
    userProfile.objects.create(userName=instance)

post_save.connect(create_user_profile, sender=User)

Cela créera automatiquement une instance d'employé lors de la création d'un nouvel utilisateur.

Si vous souhaitez étendre le modèle utilisateur et ajouter des informations supplémentaires lors de la création de l'utilisateur, vous pouvez utiliser Django-betterforms (http://django-betterforms.readthedocs.io/en/latest/multiform.html).Cela créera un formulaire d'ajout d'utilisateur avec tous les champs définis dans le modèle userProfile.

modèles.py

from django.db.models.signals import *
from __future__ import unicode_literals

class userProfile(models.Model):

    userName = models.OneToOneField(User)
    city = models.CharField(max_length=100)

    def __unicode__(self):  # __str__
        return unicode(self.userName)

formulaires.py

from django import forms
from django.forms import ModelForm
from betterforms.multiform import MultiModelForm
from django.contrib.auth.forms import UserCreationForm
from .models import *

class profileForm(ModelForm):

    class Meta:
        model = Employee
        exclude = ('userName',)


class addUserMultiForm(MultiModelForm):
    form_classes = {
        'user':UserCreationForm,
        'profile':profileForm,
    }

vues.py

from django.shortcuts import redirect
from .models import *
from .forms import *
from django.views.generic import CreateView

class addUser(CreateView):
    form_class = addUserMultiForm
    template_name = "addUser.html"
    success_url = '/your url after user created'

    def form_valid(self, form):
        user = form['user'].save()
        profile = form['profile'].save(commit=False)
        profile.userName = User.objects.get(username= user.username)
        profile.save()
        return redirect(self.success_url)

addUser.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="." method="post">
            {% csrf_token %}
            {{ form }}     
            <button type="submit">Add</button>
        </form>
     </body>
</html>

URL.py

from django.conf.urls import url, include
from appName.views import *
urlpatterns = [
        url(r'^add-user/$', addUser.as_view(), name='addDistributor'),
]

Extension du modèle utilisateur Django (UserProfile) comme un pro

J'ai trouvé ceci très utile : lien

Un extrait:

à partir de django.contrib.auth.models importer l'utilisateur

class Employee(models.Model):
    user = models.OneToOneField(User)
    department = models.CharField(max_length=100)

>>> u = User.objects.get(username='fsmith')
>>> freds_department = u.employee.department

Nouveau dans Django 1.5, vous pouvez désormais créer votre propre modèle utilisateur personnalisé (ce qui semble être une bonne chose à faire dans le cas ci-dessus).Faire référence à 'Personnalisation de l'authentification dans Django'

Probablement la nouvelle fonctionnalité la plus intéressante de la version 1.5.

C'est ce que je fais et c'est à mon avis le moyen le plus simple de le faire.définissez un gestionnaire d'objets pour votre nouveau modèle personnalisé puis définissez votre modèle.

from django.db import models
from django.contrib.auth.models import PermissionsMixin, AbstractBaseUser, BaseUserManager

class User_manager(BaseUserManager):
    def create_user(self, username, email, gender, nickname, password):
        email = self.normalize_email(email)
        user = self.model(username=username, email=email, gender=gender, nickname=nickname)
        user.set_password(password)
        user.save(using=self.db)
        return user

    def create_superuser(self, username, email, gender, password, nickname=None):
        user = self.create_user(username=username, email=email, gender=gender, nickname=nickname, password=password)
        user.is_superuser = True
        user.is_staff = True
        user.save()
        return user



  class User(PermissionsMixin, AbstractBaseUser):
    username = models.CharField(max_length=32, unique=True, )
    email = models.EmailField(max_length=32)
    gender_choices = [("M", "Male"), ("F", "Female"), ("O", "Others")]
    gender = models.CharField(choices=gender_choices, default="M", max_length=1)
    nickname = models.CharField(max_length=32, blank=True, null=True)

    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    REQUIRED_FIELDS = ["email", "gender"]
    USERNAME_FIELD = "username"
    objects = User_manager()

    def __str__(self):
        return self.username

N'oubliez pas d'ajouter cette ligne de code dans votre settings.py:

AUTH_USER_MODEL = 'YourApp.User'

C'est ce que je fais et ça marche toujours.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top