J'aimerais améliorer les fonctions d'enregistrement / d'authentification / de connexion des utilisateurs avec Django, et je suis bloqué lorsque je continue, donc je vais garder une trace.
** Lors du développement d'une application avec Django, définissez les exigences et la conception avant de lancer un projet **
** Sauf si cela a déjà été tissé par conception, etc., il est fondamentalement préférable de protéger 1 projet et 1 application jusqu'à ce que Django puisse être développé. ** **
** Même en développant en étudiant, recommencez le projet sans vous fatiguer et ne le réutilisez pas. ** **
Le didacticiel Django est terminé, donc [cet article](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) et [cet article](https://narito.ninja/blog/detail Basé sur / 38 /) J'essayais diverses choses pour créer un modèle d'application TODO avec des fonctions d'enregistrement / d'authentification / de connexion des utilisateurs dans Django, mais je détournais le projet du tutoriel car c'était le modèle ʻUser` gênant et Je suis resté coincé dans les spécifications de «SuperUser».
Lorsque vous utilisez la fonction d'enregistrement d'appartenance avec Django, utilisez essentiellement le modèle ʻUser` fourni par Django. Au contraire, tant que vous introduisez un framework, vous utiliserez probablement le mécanisme d'authentification fourni par le framework, à moins qu'il y ait quelque chose qui ne va pas avec un framework, et qu'il est définitivement intégré. Certains ont des modèles et des méthodes.
Donc, le problème à partir de là est que Django vous permet de gérer plusieurs applications dans un dossier Projet, et inversement, vous pouvez installer la même application dans plusieurs dossiers de projet.
Cependant, en fait, un seul modèle ʻUser peut être utilisé par projet. À proprement parler, Django recommande fortement de créer un modèle utilisateur personnalisé basé sur le modèle User pour le déploiement, et il doit être créé lors de la première migration. À ce moment-là, afin de gérer le modèle utilisateur avec la fonction d'authentification, la partie de ʻAUTH_USER_MODEL
définie dans settings.py
est définie, mais il est plus rapide de redémarrer le projet pour changer cela plus tard. Cela demande du temps et des efforts.
Référence
En d'autres termes, si vous souhaitez gérer plusieurs applications avec un seul projet
, vous devez décider quelle application aura les fonctions d'authentification lorsque vous lancerez projet
.
Je ne suis pas ça ... En d'autres termes, même si j'ai défini la classe User dans le didacticiel, je voulais créer une autre application et y ajouter une fonction d'authentification, alors j'ai lancé project
et j'ai juste démarré la classe User
. Cela signifie que ce sera difficile à faire.
Cependant, je ne peux pas m'empêcher de faire ce que j'ai fait, donc cette fois j'ai essayé de découvrir ce qui pouvait être fait avec le projet
existant, y compris la signification des études ultérieures.
--Personnaliser le modèle ʻUser existant ――Créez un nouveau modèle qui étend le modèle ʻUser
Créez-le dans le dossier de l'application et associez-le en utilisant ʻOneToOneField. --Modifiez ʻadmin.py
sur le côté avec le modèle User pour refléter le modèle User personnalisé et le modèle qui étend le modèle User sur l'écran de gestion.
En outre, à ce stade, le modèle qui utilise le modèle du côté de l'application TODO en tant que fonction et le modèle d'extension ʻUser` ci-dessus (qui remplace également l'enregistrement pour l'indicateur d'authentification de messagerie) sont dans des fichiers séparés.
Et, bien sûr, jouer avec models.py
devra refaire faire des migrations
, alors faisons-le soigneusement.
Excusez-moi pour l'image car dessiner un diagramme de répertoires est un problème.
L'environnement de développement sous src est ʻapp,
polls et
todo sous le dossier du projet définissent le modèle utilisateur dans chaque application, et l'application que vous voulez créer cette fois est
todo`.
Tout d'abord, nous allons personnaliser le corps du modèle ʻUser`. Référence: Personnaliser le modèle utilisateur avec Django
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) #Numéros de magasin
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)
Cette partie remplace les méthodes de création d'utilisateurs et de super-utilisateurs.
En d'autres termes, puisqu'il s'agit de la partie liée à la connexion à l'écran de gestion de Django, j'ai pris la forme de copier la partie de django.contrib.auth.models```UserManager
et d'ajouter et de corriger les parties nécessaires. ..
La source est ici.
class User(AbstractBaseUser, PermissionsMixin):
#Élément de base du modèle utilisateur.
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 Une méthode pour déterminer si un utilisateur a accès à un site
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_(
'Designates whether this user can log into this admin site.'),
)
#Une méthode pour déterminer si un utilisateur est actif
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()
#Pour le dire clairement, le champ sans maillages, le champ utilisé comme nom d'utilisateur et le champ à saisir lors de la création d'un super utilisateur sont spécifiés par le haut.
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'email'
REQUIRED_FIELD = []
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
#Méthodes d'envoi d'e-mails
def email_user(self, subject, message, from_email=None, **kwargs):
send_mail(subject, message, from_email, [self.email], **kwargs)
Cela hérite également de ʻAbstractBaseUser de
django.contrib.auth.models . Puisque
PermissionsMixina l'héritage dans la classe d'origine, il est également hérité ici. En tant que rôle, il semble s'agir d'un ensemble de méthodes liées à l'autorité.
models.BooleanField définit la valeur par défaut
par défaut pour
BooleanField dans le champ de modèle et renvoie True, False. Puisque je veux me connecter avec une adresse e-mail au lieu d'un nom d'utilisateur dans la source de référence, je supprime le champ ʻusername
et laisse le champ ʻemail jouer ce rôle. Le paramètre est ʻUSERNAME_FIELD = 'email'
.
Cette fois, j'ai laissé «nom d'utilisateur» car cette application TODO est à usage général et je veux la refactoriser en fonction de cela pour créer quelque chose avec des fonctions supplémentaires.
Au fait
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
#Défini au cas où une autre application accède à l'attribut de nom d'utilisateur, renvoie l'adresse e-mail lors de l'accès
@property
def username(self):
return self.email
Des éléments tels que sont ajoutés au besoin.
Cette fois, je n'utilise pas les champs first_name
et last_name
, donc je ne les ai pas implémentés, mais je pense que ce serait utile si vous souhaitez créer un formulaire qui vous permet d'enregistrer votre prénom et votre nom.
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 = 'Indicateur d'authentification de messagerie'
verbose_name_plural = 'Indicateur d'authentification de messagerie'
Cette fois, créez un modèle qui étend le modèle ʻUser du côté de l'application TODO. Cette fois, en plus des informations du côté du modèle ʻUser
, définissez les champs pour l'authentification du courrier.
ʻOneToOneField` est un paramètre pour définir une relation un-à-un avec un modèle.
Puisqu'il n'y a qu'un seul indicateur d'authentification pour l'utilisateur, il existe une relation un-à-un.
Il semble que plusieurs-à-un etc. seront définis par «Clé étrangère».
Après cela, supprimez models.py
pour empaqueter le modèle divisé, créez un dossiermodels
, créez-y __init __. Py
et mettez le modèle divisé dans le même dossier.
__init __. py
définit comme suit d'importer le modèle à emballer:
todo/models/__init__.py
from .todo import Todo
from .account import Activate
Ceci termine la division du modèle.
Après cela, si vous modifiez ʻadmin.py`, ce sera un paragraphe.
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
#compte d'application todo.Importer un objet Activate depuis 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',)
#L'indicateur d'authentification de courrier associé peut être géré sur l'écran de gestion du modèle utilisateur.
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',)
#Spécifiez la classe ActivateInline
inlines = [ActivateInline]
admin.site.register(User, MyUserAdmin)
admin.site.register(SampleDB)
Empruntez maintenant à django.contrib.auth.admin.py
et remplacez-le pour que vous puissiez voir votre modèle d'utilisateur personnalisé dans l'écran d'administration.
Le cœur est la partie 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)
De cette façon, le modèle ʻActivate peut également être géré du côté de l'application todo, mais il est plus pratique de le gérer avec le modèle ʻUser
car il est lié à la relation, donc importez le modèle avec de todo.models.account import Activate
. main,
Cela signifie créer une classe ʻInline du côté de la classe User. Pour le moment, au fur et à mesure que nous poursuivons le travail, nous traiterons chaque fois qu'une erreur se produira dans ʻUSERNAME_FIELD = 'email'
.
Personnaliser le modèle utilisateur avec Django Django, Personnalisation du modèle utilisateur (OneToOne) Autoriser l'inscription avec le modèle utilisateur personnalisé de Django Créer un utilisateur personnalisé avec Django AbstractBaseUser Personnaliser la méthode d'authentification à partir du document officiel D'après le document officiel django.contrib.auth
Recommended Posts