Estensione del modello utente con campi personalizzati in Django

Qual è il modo migliore per estendere il modello Utente (in bundle con l’app di autenticazione di Django) con i campi personalizzati? Vorrei anche usare l’e-mail come nome utente (per scopi di autenticazione).

Ho già visto alcuni modi per farlo, ma non posso decidere quale sia il migliore.

Il modo meno doloroso ed effettivamente consigliato da Django per farlo è attraverso una proprietà OneToOneField(User) .

Estensione del modello utente esistente

Se si desidera memorizzare le informazioni relative User , è ansible utilizzare una relazione uno-a-uno con un modello contenente i campi per ulteriori informazioni. Questo modello one-to-one viene spesso definito un modello di profilo, in quanto potrebbe archiviare informazioni non relative all’autorità di un utente del sito.

Detto questo, estendere django.contrib.auth.models.User e soppiantarlo funziona anche …

Sostituendo un modello utente personalizzato

Alcuni tipi di progetti possono avere requisiti di autenticazione per i quali il modello User incorporato di Django 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 avvertimenti e una notifica , menzionando che questo è abbastanza drastico .]

Sicuramente starei lontano dal cambiare la vera class utente nel tuo albero dei sorgenti Django e / o copiare e alterare il modulo auth.

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

Questo è 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' 

Questo creerà un profilo utente ogni volta che un utente viene salvato se viene creato. È quindi ansible utilizzare

  user.get_profile().whatever 

Ecco alcune ulteriori informazioni dai documenti

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

Aggiornamento: nota che AUTH_PROFILE_MODULE è deprecato dalla v1.5: https://docs.djangoproject.com/en/1.5/ref/settings/#auth-profile-module

Bene, un po ‘di tempo è passato dal 2008 ed è tempo di una nuova risposta. Da quando Django 1.5 sarà in grado di creare una User Class personalizzata. In realtà, al momento sto scrivendo questo, è già fuso in master, quindi puoi provarlo.

Ci sono alcune informazioni a riguardo nei documenti o se vuoi approfondire la questione, in questo commit .

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

Per le persone che sono pigri a fare clic, ecco l’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 

C’è una raccomandazione ufficiale sulla memorizzazione di ulteriori informazioni sugli utenti . Il libro Django parla anche di questo problema nella sezione Profili .

Dal momento che Django 1.5 è ansible estendere facilmente il modello utente e mantenere una singola tabella sul 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 class utente corrente nel file delle impostazioni

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

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

Una nota per persone che sviluppano librerie di terze parti: se è necessario accedere alla class utente, ricorda che le persone possono cambiarle. Usa l’aiuto ufficiale per ottenere la class giusta

 from django.contrib.auth import get_user_model User = get_user_model() 

Quello sotto è un altro approccio per estendere un utente. Sento che è più chiaro, facile, leggibile quindi sopra due approcci.

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

Utilizzando l’approccio sopra:

  1. non è necessario utilizzare user.get_profile (). newattributo per accedere alle informazioni aggiuntive relative all’utente
  2. puoi accedere direttamente ad altri nuovi attributi tramite user.newattribute

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

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

Questo creerà automaticamente un’istanza dipendente quando viene creato un nuovo utente.

Se si desidera estendere il modello utente e si desidera aggiungere ulteriori informazioni durante la creazione di un utente, è ansible utilizzare django-betterforms ( http://django-betterforms.readthedocs.io/en/latest/multiform.html ). Ciò creerà un modulo di aggiunta utente con tutti i campi definiti nel modello userProfile.

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

forms.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_classs = { '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>    Title   
{% csrf_token %} {{ form }}

urls.py

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

Estensione di Django User Model (UserProfile) come un Pro

Ho trovato questo molto utile: link

Un estratto:

da django.contrib.auth.models import User

 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 è ansible creare il proprio modello utente personalizzato (che sembra essere una buona cosa da fare in caso di sopra). Fare riferimento a “Personalizzazione dell’autenticazione in Django”

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

Questo è quello che faccio e secondo me è il modo più semplice per farlo. definire un gestore oggetti per il nuovo modello personalizzato, quindi definire il 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 settings.py :

 AUTH_USER_MODEL = 'YourApp.User' 

Questo è quello che faccio e funziona sempre.