Django のログイン認証で使用するユーザモデルをカスタマイズします。
最近知ったのですが、Django はユーザモデルをカスタマイズすることを推奨していました。
新しくプロジェクトを始める場合は、デフォルトの
User
で十分である場合でも、カスタムユーザーモデルを作成することを強く推奨します。
ユーザモデルを拡張しやすくするためです。今後、新規に Django プロジェクトを作成するときは、なるべくカスタムユーザモデルでいこうと思います。
Contents
バージョン
- Python 3.5.4
- Django 2.2.1
インストール
ユーザモデルをカスタマイズするための環境を作っていきます。
仮想環境と Django のインストール
$ python -m venv venv $ source venv/bin/activate (venv) $ pip install Django
virtualenv で Python 仮想環境を作成し、そこに Django をインストールします。
Django プロジェクト作成
(venv) $ django-admin startproject custom_auth_user (venv) $ cd custom_auth_user/ (venv) $ python manage.py startapp account
Django のプロジェクトとアプリケーションを作成します。プロジェクト名とアプリケーション名は好きにつけましょう。
実装
カスタムユーザモデルの実装に入る前に、Django ビルトインユーザモデルを確認したいと思います。
Django ビルトイン ユーザモデル
django.contrib.auth.models.User
フィールド | 必須 | 説明 |
---|---|---|
username | o | ユーザ名。認証で使用。 |
password | o | パスワード。認証で使用。 |
メールアドレス。 | ||
first_name | ファーストネーム。名前。 | |
last_name | ラストネーム。苗字。 | |
groups | グループ。 | |
user_permissions | 権限。 | |
is_staff | admin サイトにアクセスできるか? | |
is_active | このユーザは有効か? | |
is_superuser | スーパーユーザか? | |
last_login | 最終ログイン日時。 | |
date_joined | ユーザ作成日時。 |
これらが Django ビルトインユーザモデルです。認証用のユーザモデルとして settings.py にデフォルト設定されています。このままでも十分な気もしますが、要件によっては、このままではダメなケースもあると思います。
私は、ログイン認証をメールアドレスにしないといけない案件がありましたので、カスタムユーザモデルを使って実装しました。
カスタムユーザモデル
models.py
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager from django.db import models from django.utils import timezone class MyUserManager(BaseUserManager): def create_user(self, email, password): if not email: raise ValueError('Users must have an email address') user = self.model(email=self.normalize_email(email)) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email, password): user = self.create_user(email=email, password=password) user.is_superuser = True user.save(using=self._db) return user class MyUser(AbstractBaseUser): USERNAME_FIELD = 'email' REQUIRED_FIELDS = [] email = models.EmailField(unique=True, max_length=255) username = models.CharField(max_length=150, blank=True) is_active = models.BooleanField(default=True) is_superuser = models.BooleanField(default=False) date_joined = models.DateTimeField(default=timezone.now) objects = MyUserManager()
カスタムユーザモデルのクラス名を MyUser としました。そして、認証に必要だった username を USERNAME_FIELD の設定で、email に変更しています。カスタムユーザモデルは、ユーザの作成関数も独自のものにする必要があるため、カスタムユーザマネージャが必要になります。MyUserManager という名前にしました。
settings.py
INSTALLED_APPS = [ ... 'account.apps.AccountConfig', ] ... AUTH_USER_MODEL = 'account.MyUser'
カスタムユーザモデルを作成したら、それを settings.py で指定します。パスを指定するのですが、models は不要なことに注意してください。
動作確認
それでは、動作確認していきます。
まず最初に、DB のマイグレーションを実行し、manage.py createsuperuser コマンドでカスタムユーザが作成できるか確認します。
DB マイグレーション
(venv) $ python manage.py makemigrations Migrations for 'account': account/migrations/0001_initial.py - Create model MyUser (venv) $ python manage.py migrate Operations to perform: Apply all migrations: account, admin, auth, contenttypes, sessions Running migrations: Applying account.0001_initial... OK Applying contenttypes.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0001_initial... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying auth.0010_alter_group_name_max_length... OK Applying auth.0011_update_proxy_permissions... OK Applying sessions.0001_initial... OK
makemigrations コマンドでカスタムユーザ用の migration ファイルを作成し、migrate コマンドでスキーマを適用します。
スーパーユーザの作成
(venv) $ python manage.py createsuperuser Email: test@test.test Password: Password (again): Superuser created successfully.
createsuperuser コマンドでユーザを作成します。ビルトインユーザモデルの場合、最初に username の入力を求められますが、email に変わっていることが確認できます。
DB の確認
$ sqlite3 db.sqlite3 sqlite> .tables account_myuser auth_permission django_migrations auth_group django_admin_log django_session auth_group_permissions django_content_type sqlite> .schema account_myuser CREATE TABLE IF NOT EXISTS "account_myuser" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "password" varchar(128) NOT NULL, "last_login" datetime NULL, "email" varchar(255) NOT NULL UNIQUE, "username" varchar(150) NOT NULL, "is_active" bool NOT NULL, "is_superuser" bool NOT NULL, "date_joined" datetime NOT NULL); sqlite> select * from account_myuser; 1|pbkdf2_sha256$150000$u4MnNZS8Ewzb$PgMPH42orRPxEiwMFqPfsyLKw0mZ1FiwyBqh8zWcViQ=||test@test.test||1|1|2019-05-16 03:57:08.789679
実際にユーザが作成されたか DB を確認します。select * from account_myuser; で先ほど作成したカスタムユーザモデルのユーザが作成されていることが確認できました。
まとめ
Django のログイン認証で使用するユーザモデルをカスタマイズしました。
Django はカスタムユーザモデルを推奨しているので、なるべくカスタムユーザモデルを使いましょう。
カスタムユーザモデルの作り方は、まず、ユーザモデルとユーザマネージャを作成し、settings.py で指定すれば OK です。