Estensione del modello Utente con campi personalizzati in Django
-
09-06-2019 - |
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.
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:
- non è necessario utilizzareuser.get_profile().newattribute Per accedere alle informazioni aggiuntive relative all'utente
- 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.