Ich möchte die Benutzerregistrierungs- / Authentifizierungs- / Anmeldefunktionen bei Django verbessern, und ich stecke fest, wenn ich fortfahre, also werde ich ein Protokoll führen.
** Wenn Sie eine App mit Django entwickeln, definieren Sie Anforderungen und Design, bevor Sie ein Projekt starten **
** Sofern es nicht bereits durch Design usw. eingewebt wurde, ist es grundsätzlich besser, 1 Projekt und 1 Anwendung zu schützen, bis Django entwickelt werden kann. ** ** **
** Starten Sie das Projekt auch während der Entwicklung durch Studium erneut, ohne müde zu werden, und verwenden Sie es nicht wieder. ** ** **
Das Django-Tutorial ist beendet, also [dieser Artikel](https://qiita.com/okoppe8/items/54eb105c9c94c0960f14#%E6%89%8B%E9%A0%86%EF%BC%96%E3%83% 95% E3% 82% A9% E3% 83% BC% E3% 83% A0% E4% BD% 9C% E6% 88% 90) und [dieser Artikel](https://narito.ninja/blog/detail Basierend auf / 38 /) Ich habe verschiedene Dinge versucht, um eine Vorlage für eine TODO-Anwendung mit Benutzerregistrierungs- / Authentifizierungs- / Anmeldefunktionen in Django zu erstellen, aber als ich das Projekt des Tutorials umleitete, weil es problematisch war, das "Benutzermodell" und Ich halte mich an die Spezifikationen von "SuperUser".
Verwenden Sie bei Verwendung der Mitgliedschaftsregistrierungsfunktion mit Django grundsätzlich das von Django bereitgestellte Benutzermodell. Solange Sie ein Framework einführen, werden Sie wahrscheinlich den vom Framework bereitgestellten Authentifizierungsmechanismus verwenden, es sei denn, mit einem Framework stimmt etwas nicht und es ist definitiv integriert. Einige haben Modelle und Methoden.
Das Problem von hier aus ist, dass Sie mit Django mehrere Anwendungen in einem Projektordner verwalten können und umgekehrt dieselbe Anwendung in mehreren Projektordnern installieren können.
Tatsächlich kann jedoch nur ein Benutzermodell pro Projekt verwendet werden.
Genau genommen empfiehlt Django dringend, ein benutzerdefiniertes Benutzermodell zu erstellen, das auf dem Benutzermodell für die Bereitstellung basiert und bei der ersten Migration erstellt werden muss.
Zu diesem Zeitpunkt wird der in settings.py
festgelegte Teil von AUTH_USER_MODEL
festgelegt, um das Benutzermodell mit der Authentifizierungsfunktion zu behandeln. Es ist jedoch schneller, das Projekt neu zu starten, um dies später zu ändern. Es braucht Zeit und Mühe.
Referenz
Mit anderen Worten, wenn Sie mehrere Apps mit einem "Projekt" verwalten möchten, müssen Sie entscheiden, welche Anwendung die Funktionen zur Authentifizierung haben soll, wenn Sie "Projekt" starten.
Ich folge dem nicht ... Mit anderen Worten, ich habe die Benutzerklasse im Tutorial definiert, aber ich wollte eine andere Anwendung erstellen und dort eine Authentifizierungsfunktion hinzufügen. Ich habe "project" gestartet und die "User" -Klasse so wie sie ist gestartet. Es bedeutet, dass es schwierig sein wird, zu machen.
Ich kann jedoch nicht anders, als das zu tun, was ich getan habe. Deshalb habe ich dieses Mal versucht herauszufinden, was mit dem vorhandenen "Projekt" getan werden kann, einschließlich der Bedeutung für spätere Studien.
admin.py
auf der Seite mit dem Benutzermodell, um das angepasste Benutzermodell und das Modell, das das Benutzermodell erweitert, auf dem Verwaltungsbildschirm wiederzugeben.Zu diesem Zeitpunkt befinden sich das Modell, das das Modell auf der TODO-Anwendungsseite als Funktion verwendet, und das obige Erweiterungsmodell "Benutzer" (das auch den Datensatz für das Mail-Authentifizierungsflag überschreibt) in separaten Dateien.
Und natürlich muss das Herumspielen mit "models.py" "Migrationen durchführen" wiederholen, also lasst es uns vorsichtig machen.
Entschuldigen Sie das Bild, denn das Zeichnen eines Verzeichnisdiagramms ist mühsam. Die Entwicklungsumgebung unter src ist "app", "polls" und "todo" im Projektordner. Definieren Sie das Benutzermodell in jeder Anwendung, und die Anwendung, die Sie dieses Mal erstellen möchten, ist "todo".
Zuerst werden wir den "Body" -Modellkörper anpassen. Referenz: Benutzermodell mit Django anpassen
from django.db import models
from django.core.mail import send_mail
from django.contrib.auth.models import PermissionsMixin, UserManager
from django.contrib.auth.base_user import AbstractBaseUser
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from django.core.validators import EmailValidator
class CustomUserManager(UserManager):
use_in_migrations = True
def _create_user(self,email,password, **extra_fields):
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self,email,password=None, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(emai, password, **extra_fields)
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=30, unique=True)
email = models.EmailField(_('email address'), unique=True, validators=[EmailValidator('Invalid email address.')])
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=150, blank=True)
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_(
'Designates whether this user can log into this admin site.'),
)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as active.'
'Unselect this instead of deleting accounts.'
),
)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
objects = CustomUserManager()
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'email'
REQUIRED_FIELD = []
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
def email_user(self, subject, message, from_email=None, **kwargs):
send_mail(subject, message, from_email, [self.email], **kwargs)
class SampleDB(models.Model):
class Meta:
db_table = 'sample_table' # tablename
verbose_name_plural = 'sample_table' # Admintablename
sample1 = models.IntegerField('sample1', null=True, blank=True) #Speichern Sie Nummern
sample2 = models.CharField('sample2', max_length=255, null=True, blank=True)
class CustomUserManager(UserManager):
use_in_migrations = True
def _create_user(self,email,password, **extra_fields):
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self,email,password=None, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(emai, password, **extra_fields)
Dieser Teil überschreibt die Methoden zum Erstellen von Benutzern und Superusern. Mit anderen Worten, da dies der Teil ist, der sich auf die Anmeldung am Verwaltungsbildschirm von Django bezieht, habe ich den "UserManager" -Teil von "django.contrib.auth.models" kopiert und die erforderlichen Teile geändert. .. Die Quelle ist hier.
class User(AbstractBaseUser, PermissionsMixin):
#Grundelement des Benutzermodells.
username = models.CharField(max_length=30, unique=True)
email = models.EmailField(_('email address'), unique=True, validators=[EmailValidator('Invalid email address.')])
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=150, blank=True)
#admin Eine Methode, um festzustellen, ob ein Benutzer Zugriff auf eine Site hat
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_(
'Designates whether this user can log into this admin site.'),
)
#Eine Methode, um festzustellen, ob ein Benutzer aktiv ist
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as active.'
'Unselect this instead of deleting accounts.'
),
)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
objects = CustomUserManager()
#Einfach ausgedrückt werden das Mail-Dress-Feld, das als Benutzername verwendete Feld und das Feld, das beim Erstellen eines Superusers eingegeben werden muss, von oben angegeben.
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'email'
REQUIRED_FIELD = []
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
#Methoden zum Versenden von E-Mails
def email_user(self, subject, message, from_email=None, **kwargs):
send_mail(subject, message, from_email, [self.email], **kwargs)
Dies erbt auch "AbstractBaseUser" von "django.contrib.auth.models".
Da PermissionsMixin
in der ursprünglichen Klasse vererbt ist, wird es auch hier vererbt.
Als eine Rolle scheint es eine Sammlung von Methoden zu sein, die sich auf Autorität beziehen.
models.BooleanField
legt den Standardwert für BooleanField
im Modellfeld fest und gibt True, False zurück.
In der Referenzquelle möchte ich mich mit einer E-Mail-Adresse anstelle eines Benutzernamens anmelden. Daher lösche ich das Feld "Benutzername" und lasse das Feld "E-Mail" diese Rolle spielen.
Die Einstellung ist "USERNAME_FIELD =" email ".
Dieses Mal habe ich "Benutzername" verlassen, weil diese TODO-App für allgemeine Zwecke gedacht ist und ich sie basierend darauf umgestalten möchte, um etwas mit zusätzlichen Funktionen zu erstellen.
Apropos
def get_full_name(self):
"""Return the first_name plus the last_name, with a space in
between."""
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
"""Return the short name for the user."""
return self.first_name
#Definiert für den Fall, dass eine andere Anwendung auf das Attribut Benutzername zugreift und beim Zugriff die E-Mail-Adresse zurückgibt
@property
def username(self):
return self.email
Elemente wie werden nach Bedarf hinzugefügt. Dieses Mal verwende ich nicht die Felder "Vorname" und "Nachname", daher habe ich sie nicht implementiert, aber ich denke, es wäre nützlich, wenn Sie ein Formular erstellen möchten, mit dem Sie Ihren Vor- und Nachnamen registrieren können.
todo/models/account.py
from django.conf import settings
from django.db import models
from django.core import validators
class Activate(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
key = models.CharField(max_length=255, blank=True, unique=True)
expiration_date = models.DateTimeField(blank=True, null=True)
def __str__(self):
return self.key
class Meta:
verbose_name = 'E-Mail-Authentifizierungsflag'
verbose_name_plural = 'E-Mail-Authentifizierungsflag'
Erstellen Sie dieses Mal ein Modell, das das Benutzermodell auf der TODO-Anwendungsseite erweitert.
Dieses Mal definieren Sie zusätzlich zu den Informationen auf der Modellseite "Benutzer" die Felder für die E-Mail-Authentifizierung.
OneToOneField
ist eine Einstellung zum Definieren einer Eins-zu-Eins-Beziehung zu einem Modell.
Da es nur ein Authentifizierungsflag für den Benutzer gibt, besteht eine Eins-zu-Eins-Beziehung.
Es scheint, dass viele zu eins usw. durch "Fremdschlüssel" definiert werden.
Löschen Sie danach "models.py", um das geteilte Modell zu verpacken, erstellen Sie einen "Modelle" -Ordner, erstellen Sie "__init __. Py" darin und legen Sie das geteilte Modell in demselben Ordner ab.
__init __. py
definiert das Importieren des zu verpackenden Modells wie folgt:
todo/models/__init__.py
from .todo import Todo
from .account import Activate
Damit ist die Modellaufteilung abgeschlossen.
Wenn Sie danach "admin.py" ändern, handelt es sich um einen Absatz.
app/admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserChangeForm, UserCreationForm
from django.utils.translation import ugettext_lazy as _
from .models import User
#todo Anwendungskonto.Import Aktiviere Objekt von py
from todo.models.account import Activate
from.models import SampleDB
class MyUserChangeForm(UserChangeForm):
class Meta:
model = User
fields = '__all__'
class MyUserCreationForm(UserCreationForm):
class Meta:
model = User
fields = ('email',)
#Das zugehörige Mail-Authentifizierungsflag kann auf dem Verwaltungsbildschirm des Benutzermodells behandelt werden.
class ActivateInline(admin.StackedInline):
model = Activate
max_num = 1
can_delete = False
class MyUserAdmin(UserAdmin):
fieldsets = (
(None, {'fields': ('username', 'password')}),
(_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
(_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
'groups', 'user_permissions')}),
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2'),
}),
)
form = MyUserChangeForm
add_form = MyUserCreationForm
list_display = ('username','email', 'first_name', 'last_name', 'is_staff')
list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
search_fields = ('username','email', 'first_name', 'last_name')
ordering = ('email',)
#Geben Sie die ActivateInline-Klasse an
inlines = [ActivateInline]
admin.site.register(User, MyUserAdmin)
admin.site.register(SampleDB)
Leihen Sie sich jetzt von django.contrib.auth.admin.py
aus und überschreiben Sie diese, damit Sie Ihr benutzerdefiniertes Benutzermodell im Admin-Bildschirm sehen können.
Das Herz ist der Teil "from todo.models.account import Activate".
todo/admin.py
from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.admin import UserAdmin as AuthUserAdmin
from django.contrib.auth.forms import UserChangeForm, UserCreationForm
from django.utils.translation import ugettext_lazy as _
from .models import Todo, Activate
from app.models import User
# Register your models here.
class TodoAdmin(admin.ModelAdmin):
fields = ['todo_title', 'memo', 'datetime', 'tags']
list_display = ('todo_title', 'datetime', 'created_at', 'tag_list')
list_display_links = ('todo_title', 'datetime','tag_list')
def get_queryset(self, request):
return super().get_queryset(request).prefetch_related('tags')
def tag_list(self, obj):
return u", ".join(o.name for o in obj.tags.all())
pass
admin.site.register(Todo,TodoAdmin)
admin.site.register(Activate)
Auf diese Weise kann das "Activate" -Modell auch auf der Seite der Aufgabenanwendung verwaltet werden. Es ist jedoch bequemer, es mit dem "User" -Modell zu verwalten, da es mit der Beziehung zusammenhängt. Importieren Sie das Modell daher mit "from todo.models.account import Activate". Hand, Dies bedeutet, dass auf der Seite der Benutzerklasse eine Inline-Klasse erstellt wird. Während wir mit der Arbeit fortfahren, werden wir uns vorerst jedes Mal darum kümmern, wenn ein Fehler in "USERNAME_FIELD =" email "" auftritt.
Benutzermodell mit Django anpassen Django, Anpassung des Benutzermodells (OneToOne) Anmeldung mit Djangos benutzerdefiniertem Benutzermodell zulassen Erstellen Sie einen benutzerdefinierten Benutzer mit Django AbstractBaseUser Authentifizierungsmethode aus offiziellem Dokument anpassen Aus dem offiziellen Dokument django.contrib.auth
Recommended Posts