Hello World.
LiSMOtechの久津間です。
今回の記事では既存のユーザー情報を変更、扱うためのカスタムユーザーについて記載していきます。
この記事を読み進めていければ、カスタムユーザーを使ったDjangoの開発を行うことができますので是非ご参考にしてください。
それでは、本題に入っていきましょう!
Djangoの公式サイトではカスタムユーザーを作成することを推奨しています。
標準Userモデルをインストール後に使うことができますが、 独自のWebアプリケーションを作成する場合であれば、ユーザー情報の必要項目は変わるはずです。
その他にも、ログイン時における標準Userモデルではユーザーネームが必要となりますが、こちらをメールアドレスなどに変更して利用したい場合もあります。
そういった理由からカスタムユーザーを作成することを推奨しています。
AbstractBaseUser、PermissionsMixinを継承してカスタムユーザーを作成していきます。
※継承元のAbstractBaseUserは以下に定義されていますので、確認しておきましょう。
django.contrib.auth.base_user
先ずはアプリケーションを作成し、settingsに作成したアプリを追加します。
python manage.py startapp accounts
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'accounts.apps.AccountsConfig',
]
それでは作成したカスタムユーザー用のモデルを編集していきます。
django.contrib.auth.base_userのAbstractUserクラスを全てコピーし、カスタムユーザー用のモデルに貼り付け、必要箇所を変更します。
# models.py
from django.db import models
from django.apps import apps
from django.contrib import auth
from django.core.mail import send_mail
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.base_user import AbstractBaseUser
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from django.contrib.auth.validators import UnicodeUsernameValidator
from django.contrib.auth.base_user import BaseUserManager
class CustomUser(AbstractBaseUser, PermissionsMixin):
"""
An abstract base class implementing a fully featured User model with
admin-compliant permissions.
Username and password are required. Other fields are optional.
"""
username_validator = UnicodeUsernameValidator()
username = models.CharField(
_('username'),
max_length=150,
help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
validators=[username_validator],
error_messages={
'unique': _("A user with that username already exists."),
},
)
first_name = models.CharField(_('first name'), max_length=150, blank=True)
last_name = models.CharField(_('last name'), max_length=150, blank=True)
email = models.EmailField(_('email address'), unique=True)
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_('Designates whether the 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 = UserManager()
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
# abstract = True
def clean(self):
super().clean()
self.email = self.__class__.objects.normalize_email(self.email)
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
def email_user(self, subject, message, from_email=None, **kwargs):
"""Send an email to this user."""
send_mail(subject, message, from_email, [self.email], **kwargs)
【はまりポイント】
abstract = Trueをコメントアウトしておかないと以下のようなエラーメッセージが表示されます。
django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL refers to model ‘accounts.CustomUser’ that has not been installed
abstract = Trueが設定されていると、抽象クラスとみなされて実体が作成されないみたいです。
そのため、モデルを参照しても「モデルが存在しない」といったエラーが発生します。
作成したカスタムユーザークラスの上部にカスタムユーザーマネージャークラスを作成します。
こちらの作成は、ターミナルでユーザーを作成する際に呼ばれるUserManagerを、カスタムユーザー用に変更するためです。
# models.py
class UserManager(BaseUserManager):
use_in_migrations = True
def _create_user(self, email, password, **extra_fields):
"""
Create and save a user with the given email, and password.
"""
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
# Lookup the real model class from the global app registry so this
# manager method can be used in migrations. This is fine because
# managers are by definition working on the real model.
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=None, password=None, **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(email, password, **extra_fields)
settings.pyにおいて、認証モデルを変更する記述を追加します。
AUTH_USER_MODEL = 'accounts.CustomUser'
以下のコマンドを実行し、エラー等出なければ大丈夫です。
python manage.py makemigrations
python manage.py migrate
アドミンのユーザーを作成します。
登録する際はメールアドレスによる登録ができるようになっているはずです。
python manage.py createsuperuser
管理画面でカスタムユーザーを管理するように設定します。
accounts配下のadmin.pyに以下の記述を行います。
from django.contrib import admin
from django.contrib.auth import get_user_model
CustomUser = get_user_model()
admin.site.register(CustomUser)
ここまでの作業が完了したら、後は管理画面にでもアクセスしてみましょう。
以下のようにメールアドレスを指定したログインを求められるようになるはずです。
こちらで紹介した以外にもカスタムユーザーを作成する方法がありますが、本件の方法は柔軟性が高くなるのでおすすめです。
是非、一度試してみてください。
NEXTGATE LiSMOtechでは中小企業を中心にブランディング・WEBマーケティングを活用したWEB戦略を提供しています。
企業課題・問題に関するご相談、WEBサイト制作やグラフィックデザイン制作のクリエイティブに関するご相談やご質問、お見積りなどお気軽にお問い合わせください。
平日10:00〜19:00
© NEXTGATE LiSMOtech All rights reserved