Erweitern des Benutzermodells mit benutzerdefinierten Feldern in Django
-
09-06-2019 - |
Frage
Was ist der beste Weg, das Benutzermodell (im Paket mit der Authentifizierungs-App von Django) um benutzerdefinierte Felder zu erweitern?Eventuell möchte ich auch die E-Mail als Benutzernamen verwenden (zur Authentifizierung).
Ich habe schon einen gesehen wenige Wege Ich möchte es tun, kann mich aber nicht entscheiden, welches das Beste ist.
Lösung
Der am wenigsten schmerzhafte und tatsächlich von Django empfohlene Weg, dies zu tun, ist a OneToOneField(User)
Eigentum.
Erweiterung des bestehenden Benutzermodells
…
Wenn Sie Informationen im Zusammenhang mit speichern möchten
User
, können Sie a verwenden Eins-zu-eins-Beziehung zu einem Modell, das die Felder für zusätzliche Informationen enthält.Dieses Eins-zu-eins-Modell wird oft als Profilmodell bezeichnet, da es möglicherweise nicht authentisierungsbezogene Informationen über einen Site-Benutzer speichert.
Das heißt, verlängern django.contrib.auth.models.User
und das Ersetzen funktioniert auch ...
Ersetzen eines benutzerdefinierten Benutzermodells
Für einige Arten von Projekten gelten möglicherweise Authentifizierungsanforderungen, die in Django integriert sind
User
Modell ist nicht immer angemessen.Auf einigen Websites ist es beispielsweise sinnvoller, eine E-Mail-Adresse anstelle eines Benutzernamens als Identifikationsmerkmal zu verwenden.[Hrsg.: Es folgen zwei Warnungen und eine Benachrichtigung, erwähnend, dass dies der Fall ist ziemlich drastisch.]
Ich würde auf jeden Fall davon Abstand nehmen, die tatsächliche Benutzerklasse in Ihrem Django-Quellbaum zu ändern und/oder das Authentifizierungsmodul zu kopieren und zu ändern.
Andere Tipps
Notiz:Diese Antwort ist veraltet.Sehen Sie sich andere Antworten an, wenn Sie Django 1.7 oder höher verwenden.
So mache ich es.
#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'
Dadurch wird jedes Mal, wenn ein Benutzer erstellt wird, ein Benutzerprofil erstellt.Sie können es dann verwenden
user.get_profile().whatever
Hier sind einige weitere Informationen aus den Dokumenten
http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
Aktualisieren: Bitte beachte, dass AUTH_PROFILE_MODULE
ist seit v1.5 veraltet: https://docs.djangoproject.com/en/1.5/ref/settings/#auth-profile-module
Nun, seit 2008 ist einige Zeit vergangen und es ist Zeit für eine neue Antwort.Seit Django 1.5 können Sie benutzerdefinierte Benutzerklassen erstellen.Tatsächlich ist es zu dem Zeitpunkt, als ich dies schreibe, bereits in den Master eingebunden, sodass Sie es ausprobieren können.
Es gibt einige Informationen dazu in Dokumente oder wenn Sie tiefer in die Materie eintauchen möchten, in dieses Commit.
Alles, was Sie tun müssen, ist hinzuzufügen AUTH_USER_MODEL
zu den Einstellungen mit dem Pfad zur benutzerdefinierten Benutzerklasse, die beide erweitert AbstractBaseUser
(anpassbarere Version) oder AbstractUser
(Mehr oder weniger alte Benutzerklasse, die Sie erweitern können).
Für Leute, die klickfaul sind, hier ein Codebeispiel (entnommen aus Dokumente):
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
Seit Django 1.5 können Sie das Benutzermodell problemlos erweitern und eine einzelne Tabelle in der Datenbank behalten.
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"))
Sie müssen es auch als aktuelle Benutzerklasse in Ihrer Einstellungsdatei konfigurieren
# supposing you put it in apps/profiles/models.py
AUTH_USER_MODEL = "profiles.UserProfile"
Wenn Sie viele Benutzereinstellungen hinzufügen möchten, ist die Option OneToOneField möglicherweise die bessere Wahl.
Ein Hinweis für Leute, die Bibliotheken von Drittanbietern entwickeln:Wenn Sie auf die Benutzerklasse zugreifen müssen, denken Sie daran, dass diese geändert werden kann.Nutzen Sie den offiziellen Helfer, um die richtige Klasse zu finden
from django.contrib.auth import get_user_model
User = get_user_model()
Es gibt eine offizielle Empfehlung dazu Speicherung zusätzlicher Informationen über Benutzer.Das Django-Buch behandelt dieses Problem ebenfalls in einem Abschnitt Profile.
Das Folgende ist ein weiterer Ansatz zum Erweitern eines Benutzers.Meiner Meinung nach ist es klarer, einfacher und lesbarer als die beiden oben genannten Ansätze.
http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/
Verwendung des obigen Ansatzes:
- Sie müssen es nicht verwendenuser.get_profile().newattribute So greifen Sie auf die zusätzlichen Informationen im Zusammenhang mit dem Benutzer zu
- Sie können einfach direkt auf zusätzliche neue Attribute zugreifenuser.newattribute
Sie können das Benutzerprofil einfach erweitern, indem Sie jedes Mal, wenn ein Benutzer erstellt wird, mithilfe von Django-Post-Save-Signalen einen neuen Eintrag erstellen
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)
Dadurch wird automatisch eine Mitarbeiterinstanz erstellt, wenn ein neuer Benutzer erstellt wird.
Wenn Sie das Benutzermodell erweitern und beim Erstellen eines Benutzers weitere Informationen hinzufügen möchten, können Sie django-betterforms (http://django-betterforms.readthedocs.io/en/latest/multiform.html).Dadurch wird ein Formular zum Hinzufügen eines Benutzers mit allen im userProfile-Modell definierten Feldern erstellt.
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)
Formen.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,
}
Ansichten.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'),
]
Erweitern Sie das Django-Benutzermodell (UserProfile) wie ein Profi
Ich fand das sehr nützlich: Verknüpfung
Ein Auszug:
aus django.contrib.auth.models Benutzer importieren
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
Neu in Django 1.5: Jetzt können Sie Ihr eigenes benutzerdefiniertes Benutzermodell erstellen (was im obigen Fall eine gute Sache zu sein scheint).Beziehen auf „Anpassen der Authentifizierung in Django“
Wahrscheinlich die coolste neue Funktion in Version 1.5.
Das mache ich und es ist meiner Meinung nach der einfachste Weg, dies zu tun.Definieren Sie einen Objektmanager für Ihr neues benutzerdefiniertes Modell und definieren Sie dann Ihr Modell.
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
Vergessen Sie nicht, diese Codezeile in Ihre Datei einzufügen settings.py
:
AUTH_USER_MODEL = 'YourApp.User'
Das mache ich und es funktioniert immer.