C'est une bonne idée de définir un modèle utilisateur personnalisé dans Django. Dans ce tutoriel, on ajoutera au modèle un certain nombre de champs tels que la date de naissance, l'adresse, le numéro de téléphone. On rendra également tous ces champs modifiables dans l'admin Django et Wagtail.
Jetons d'abord un œil à l'admin. Pour ce faire, on a besoin d'un superutilisateur, alors créez-en un, si vous ne l'avez pas déjà fait:
python3 manage.py createsuperuser
Créez un nom d'utilisateur et un mot de passe et fournissez une adresse e-mail lorsque vous y êtes invité. Dans un projet Wagtail, l'admin Django traditionnel se trouve à http://127.0.0.1:8000/django-admin (sans Wagtail, c'est à … / admin). Si vous vous y connectez, notre modèle d'utilisateur personnalisé n'est pas là. Pour l'identifier dans votre admin, mettez ce qui suit dans le fichier admin.py
de votre projet:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import CustomUser
class CustomUserAdmin(UserAdmin):
add_form = UserCreationForm
form = UserChangeForm
model = CustomUser
list_display = ['pk', 'email', 'username', 'first_name', 'last_name']
add_fieldsets = UserAdmin.add_fieldsets + (
(None, {'fields': ('email', 'first_name', 'last_name',)}),
)
fieldsets = UserAdmin.fieldsets
admin.site.register(CustomUser, CustomUserAdmin)
UserCreationForm
et UserChangeForm
nous permettent de créer et de modifier des utilisateurs dans notre admin. L'attribut list_display
contrôle les champs affichés dans la vue d'ensemble de l'admin et fieldsets
lesquels qui peuvent être créés ou édités. Vérifiez maintenant http://127.0.0.1:8000/django-admin: l'utilisateur personnalisé est visible dans admin et les utilisateurs peuvent être créés et modifiés.
Jusqu'à présent, on n'a rien de plus que les champs utilisateur standard de Django. Il est temps d'ajouter quelques champs supplémentaires dans models.py
de l'une de nos applications (appelée userauth
). Je vais ajouter tous les champs à la fois et les expliquer ci-dessous.
from django.contrib.auth.models import AbstractUser
from django.core.validators import RegexValidator
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_countries.fields import CountryField
class CustomUser(AbstractUser):
display_name = models.CharField(verbose_name=_("Display name"), max_length=30, help_text=_("Will be shown e.g. when commenting"))
date_of_birth = models.DateField(verbose_name=_("Date of birth"), blank=True, null=True)
address1 = models.CharField(verbose_name=_("Address line 1"), max_length=1024, blank=True, null=True)
address2 = models.CharField(verbose_name=_("Address line 2"), max_length=1024, blank=True, null=True)
zip_code = models.CharField(verbose_name=_("Postal Code"), max_length=12, blank=True, null=True)
city = models.CharField(verbose_name=_("City"), max_length=1024, blank=True, null=True)
country = CountryField(blank=True, null=True)
phone_regex = RegexValidator(regex=r"^\+(?:[0-9]●?){6,14}[0-9]$", message=_("Enter a valid international mobile phone number starting with +(country code)"))
mobile_phone = models.CharField(validators=[phone_regex], verbose_name=_("Mobile phone"), max_length=17, blank=True, null=True)
additional_information = models.CharField(verbose_name=_("Additional information"), max_length=4096, blank=True, null=True)
photo = models.ImageField(verbose_name=_("Photo"), upload_to='photos/', default='photos/default-user-avatar.png')
class Meta:
ordering = ['last_name']
def __str__(self):
return f"{self.username}: {self.first_name} {self.last_name}"
Le nom d'affichage (display_name
) parle de lui-même. On a ajouté la possibilité de traduire le nom détaillé, en utilisant gettext_lazy
. Lorsque vous êtes sûr que vous n'utiliserez qu'une seule langue, vous pouvez bien sûr l'omettre. Dans ce didacticiel, on ajoutera systématiquement la fonctionnalité de traduction pour toutes les phrases 'lisibles par l'homme'. Le champ date de naissance n'est pas obligatoire, comme l'indiquent les paramètres blank = True, null = True
. Les champs d'adresse parlent d'eux-mêmes, à l'exception de CountryField
. Ce n'est pas Django standard, il est importé d'un paquet appelé django-countries
. Cela nous permet de choisir un pays dans une liste de tous les pays du monde, au lieu de simplement taper le pays dans un champ de texte. On installe le package avec
pip3 install django-countries
Ajoutez django_countries
à la liste des INSTALLED_APPS
dans settings/base.py
et ajoutez-le également à requirements.txt
. Le champ phone_regex
est un RegexValidator
dont le modèle correspond aux numéros de téléphone internationaux. Bien sûr, cela ne garantit pas que le numéro de téléphone est valide, mais il offre une certaine protection contre la saisie erronée. Le champ d'expression régulière est introduit dans le champ de téléphone portable .
Le Django ImageField
standard place les images téléchargées dans le répertoire indiqué par le champ upload_to
, préfixé par le paramètre MEDIA_ROOT
dans les paramètres. Puisque notre racine média est notre répertoire de base plus media
, les images téléchargées seront placées dans /media/photos/
. On a également ajouté une image par défaut, dans le répertoire photos/
. En raison de la façon dont Django gère les fichiers , il préfixera MEDIA_ROOT
sur le chemin de l'image par défaut. Cela signifie qu'on doit placer notre image par défaut dans le même répertoire /media/photos/
. Le placement manuel de fichiers dans MEDIA_ROOT
est une exception, car il n'est normalement utilisé que pour le téléchargement de fichiers; il existe d'autres façons de fournir une image par défaut si vous voulez éviter cela.
On a également défini un ordre de nos utilisateurs (par nom de famille) et une représentation, utile lors de la visualisation des utilisateurs en admin. Les champs username
, last_name
et first_name
sont mis à notre disposition via le modèle AbstractUser
.
Notre modèle d'utilisateur est terminé, on doit maintenant ajouter les champs supplémentaires à notre admin. Tout d'abord, dans CustomUserAdmin
dans admin.py
, ajoutez les champs supplémentaires à add_fieldsets
et fieldsets
:
add_fieldsets = UserAdmin.add_fieldsets + (
(None, {'fields': ('email', 'first_name', 'last_name', 'display_name', 'date_of_birth', 'address1', 'address2', 'zip_code', 'city', 'country', 'mobile_phone', 'additional_information', 'photo',)}),
)
fieldsets = UserAdmin.fieldsets + (
(None, {'fields': ('display_name', 'date_of_birth', 'address1', 'address2', 'zip_code', 'city', 'country', 'mobile_phone', 'additional_information', 'photo',)}),
)
On doit migrer notre base de données pour intégrer tous les nouveaux champs:
python3 manage.py makemigrations
python3 manage.py migrate
Lorsqu'on exécute maintenant le serveur et qu'on va à l'admin Django, on voit que tous les champs sont là!
Il est temps de regarder l'admin Wagtail à http://127.0.0.1:8000/admin. Seuls les champs standard sont là maintenant, on doit donc ajouter les champs supplémentaires. Wagtail a également un UserCreationForm
et un UserEditForm
(nom légèrement différent ici), on ajoute donc ce qui suit à forms.py
:
from .models import CustomUser
from wagtail.users.forms import UserCreationForm, UserEditForm
class WagtailUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = CustomUser
widgets = {'date_of_birth': forms.DateInput(attrs={'type':'date'})}
class WagtailUserEditForm(UserEditForm):
class Meta(UserEditForm.Meta):
model = CustomUser
widgets = {'date_of_birth': forms.DateInput(attrs={'type':'date'})}
Notez qu'on a ajouté un widget DateInput
de la bibliothèque forms
de Django, qui nous permet de choisir des dates dans un calendrier.
On n'a pas encore fini. Wagtail a besoin de modèles create.html
et edit.html
pour utiliser ces formulaires et les attend à un certain endroit. On suivra la structure de répertoire de modèles de Django et placerons tous les modèles de l'application userauth
dans le répertoire userauth/templates/userauth
. Pour permettre à Django de trouver ces modèles, ajoutez le chemin suivant à la variable TEMPLATES
dans settings/base.py
:
os.path.join(BASE_DIR, 'userauth/templates/userauth/'),
Dans ce répertoire, ajoutez deux autres sous-répertoires wagtailusers/users
, puis ajoutez les deux modèles suivants:
{% extends "wagtailusers/users/create.html" %}
{% block extra_fields %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.display_name %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.date_of_birth %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.address1 %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.address2 %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.zip_code %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.city %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.country %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.mobile_phone %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.additional_information %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.photo %}
{% endblock extra_fields %}
Idem dans edit.html
, sauf pour la première ligne:
{% extends "wagtailusers/users/edit.html" %}
Enfin, on doit ajouter les paramètres suivants dans notre settings/base.py
:
WAGTAIL_USER_CREATION_FORM = 'userauth.forms.WagtailUserCreationForm'
WAGTAIL_USER_EDIT_FORM = 'userauth.forms.WagtailUserEditForm'
WAGTAIL_USER_CUSTOM_FIELDS = ['display_name', 'date_of_birth', 'address1', 'address2', 'zip_code', 'city', 'country', 'mobile_phone', 'additional_information', 'photo',]
Maintenant, exécutez le serveur et accédez à http://127.0.0.1:8000/admin pour vérifier que tous les nouveaux champs sont là!
Lisez plus sur la connexion et l'inscription d'utilisateurs personnalisés et d'autres processus d'authentification.
Commentez cet article (connectez-vous d'abord ou confirmez par nom et email ci-dessous)