Domanda

Qual è il modo migliore per estendere il modello Utente (in bundle con l'app di autenticazione di Django) con campi personalizzati?Vorrei anche eventualmente utilizzare l'e-mail come nome utente (a fini di autenticazione).

Ho già visto un pochi modi farlo, ma non riesco a decidere quale sia il migliore.

È stato utile?

Soluzione

Il modo meno doloroso e in effetti consigliato da Django per farlo è attraverso a OneToOneField(User) proprietà.

Estensione del modello utente esistente

Se desideri memorizzare informazioni relative a User, puoi usare a relazione uno a uno a un modello contenente i campi per informazioni aggiuntive.Questo modello uno a uno è spesso chiamato modello di profilo, poiché potrebbe memorizzare informazioni non correlate all'autenticazione su un utente del sito.

Detto questo, in estensione django.contrib.auth.models.User e funziona anche sostituendolo...

Sostituzione di un modello utente personalizzato

Alcuni tipi di progetti potrebbero avere requisiti di autenticazione per i quali Django è integrato User il modello non è sempre appropriato.Ad esempio, su alcuni siti ha più senso utilizzare un indirizzo email come token di identificazione anziché un nome utente.

[Ed: Seguono due avvisi e una notifica, menzionando che questo è piuttosto drastico.]

Sicuramente starei lontano dal modificare la classe User effettiva nel tuo albero dei sorgenti Django e/o copiare e alterare il modulo di autenticazione.

Altri suggerimenti

Nota:questa risposta è deprecata.vedi altre risposte se stai utilizzando Django 1.7 o successivo.

Ecco come lo faccio.

#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'

Ciò creerà un profilo utente ogni volta che un utente viene salvato se viene creato.È quindi possibile utilizzare

  user.get_profile().whatever

Ecco alcune informazioni aggiuntive dai documenti

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

Aggiornamento: Tienilo presente AUTH_PROFILE_MODULE è deprecato dalla versione 1.5: https://docs.djangoproject.com/en/1.5/ref/settings/#auth-profile-module

Bene, è passato del tempo dal 2008 ed è tempo di dare qualche nuova risposta.A partire da Django 1.5 sarai in grado di creare classi Utente personalizzate.In realtà, nel momento in cui scrivo, è già integrato nel master, quindi puoi provarlo.

Ci sono alcune informazioni a riguardo in documenti o se vuoi approfondire l'argomento, in questo impegno.

Tutto quello che devi fare è aggiungere AUTH_USER_MODEL alle impostazioni con percorso alla classe utente personalizzata, che si estende sia AbstractBaseUser (versione più personalizzabile) o AbstractUser (Classe utente più o meno vecchia che puoi estendere).

Per le persone pigre nel fare clic, ecco un esempio di codice (tratto da documenti):

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

A partire da Django 1.5 puoi facilmente estendere il modello utente e mantenere un'unica tabella nel database.

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

È inoltre necessario configurarlo come classe utente corrente nel file delle impostazioni

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

Se desideri aggiungere molte preferenze degli utenti, l'opzione OneToOneField potrebbe essere una scelta migliore.

Una nota per le persone che sviluppano librerie di terze parti:se devi accedere alla classe utente ricorda che le persone possono cambiarla.Usa l'aiutante ufficiale per ottenere la lezione giusta

from django.contrib.auth import get_user_model

User = get_user_model()

C'è una raccomandazione ufficiale su memorizzazione di informazioni aggiuntive sugli utenti.Anche il Django Book discute questo problema nella sezione Profili.

Quello seguente è un altro approccio per estendere un utente.Sento che è più chiaro, facile e leggibile rispetto ai due approcci precedenti.

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

Utilizzando l'approccio sopra:

  1. non è necessario utilizzareuser.get_profile().newattribute Per accedere alle informazioni aggiuntive relative all'utente
  2. Puoi accedere direttamente a nuovi attributi aggiuntivi tramiteutente.nuovoattributo

Puoi semplicemente estendere il profilo utente creando una nuova voce ogni volta che l'utente viene creato utilizzando i segnali di salvataggio post di Django

modelli.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)

Ciò creerà automaticamente un'istanza del dipendente quando viene creato un nuovo utente.

Se desideri estendere il modello utente e desideri aggiungere ulteriori informazioni durante la creazione dell'utente, puoi utilizzare django-betterforms (http://django-betterforms.readthedocs.io/en/latest/multiform.html).Verrà creato un modulo di aggiunta utente con tutti i campi definiti nel modello userProfile.

modelli.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)

forme.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,
    }

views.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>

urls.py

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

Estendi il modello utente Django (Profilo utente) come un professionista

Ho trovato questo molto utile: collegamento

Un estratto:

da django.contrib.auth.models importa l'utente

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

Novità in Django 1.5, ora puoi creare il tuo modello utente personalizzato (che sembra essere una buona cosa da fare nel caso precedente).Fare riferimento a "Personalizzare l'autenticazione in Django"

Probabilmente la nuova funzionalità più interessante della versione 1.5.

Questo è quello che faccio ed è secondo me il modo più semplice per farlo.definisci un gestore oggetti per il tuo nuovo modello personalizzato, quindi definisci il tuo modello.

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

Non dimenticare di aggiungere questa riga di codice nel tuo file settings.py:

AUTH_USER_MODEL = 'YourApp.User'

Questo è quello che faccio e funziona sempre.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top