Djangoで認証ユーザーモデルをカスタマイズする
スポンサーリンク
Djangoで認証を行ったりした際に得られる User オブジェクトですが、デフォルトのままだと不要なデータが多かったり、必要なフィールドがなかったりします。
そんなときのために、今回はデフォルトのモデルである django.contrib.auth.models.User
をカスタマイズして、新しい User モデルを作成する方法について解説します。
プロジェクトを作成
お決まりの racchai プロジェクトを作成します。
$ django-admin startproject racchai
django のインストールがまだという方はこちらを参考にインストールしておきましょう。
プロジェクトが作成できたら、racchai プロジェクトをINSTALLED_APPS
に追加しておきます。
# Application definition INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'racchai', )
プロジェクトの作成はこれでおしまいです。
データベースの設定
racchai/settings.pyを見てみましょう。
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } }
初期設定では sqliteを使うことになっていますね。本記事では MySQL を使って進めていきますので、MySQL を使うように設定を変更しておきます。
mysql のユーザー名およびパスワードについては自身の環境にあわせて置き換えてください。
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'racchai', 'USER': 'root', 'PASSWORD': 'root', 'HOST': 'localhost', } }
上記の設定で、ローカルにインストールされた MySQL の racchai というデータベースを参照するようになりました。
さっそくデータベースとテーブルを作成してみましょう。
っとその前に、まだ python から MySQL へアクセスするためのドライバをインストールしていませんので、インストールしておく必要があります。
$ pip install MySQL-python
これで準備が整いましたので、データベースとテーブルを作成します。
$ mysql -uroot -p -e "CREATE DATABASE racchai"; $ ./manage.py migrate Operations to perform: Synchronize unmigrated apps: staticfiles, messages Apply all migrations: admin, contenttypes, auth, sessions Synchronizing apps without migrations: Creating tables... Running deferred SQL... Installing custom SQL... Running migrations: Rendering model states... DONE Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying contenttypes.0002_remove_content_type_name... 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 sessions.0001_initial... OK
はい、作成されました。
ではユーザーモデルに対応するテーブル情報を見てみましょう。
$ mysql -uroot -p racchai mysql> desc auth_user; +--------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | password | varchar(128) | NO | | NULL | | | last_login | datetime(6) | YES | | NULL | | | is_superuser | tinyint(1) | NO | | NULL | | | username | varchar(30) | NO | UNI | NULL | | | first_name | varchar(30) | NO | | NULL | | | last_name | varchar(30) | NO | | NULL | | | email | varchar(254) | NO | | NULL | | | is_staff | tinyint(1) | NO | | NULL | | | is_active | tinyint(1) | NO | | NULL | | | date_joined | datetime(6) | NO | | NULL | | +--------------+--------------+------+-----+---------+----------------+
いろいろ定義されていますね。次はいよいよカスタマイズする方法です。
RacchaiUserモデルを作成する
今回は以下のようなモデルを作成してみます。
- テーブル名を
racchai_user
とする - ログイン名として
email
フィールドを持つ - twitter の URL を持つ
ではやってみます。
racchai/models.py というファイルを作り、その中で RacchaiUser
クラスを定義しましょう。
from django.db import models from django.contrib.auth.models import AbstractBaseUser, BaseUserManager class RacchaiUserManager(BaseUserManager): def create_user(self, email, password=None, **extra_fields): if not email: raise ValueError('Users must have a email address') email = RacchaiUserManager.normalize_email(email) user = self.model(email=email, **extra_fields) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email, password): return self.create_user(email, password) class RacchaiUser(AbstractBaseUser): email = models.EmailField(max_length=128, unique=True) twitter_url = models.URLField() USERNAME_FIELD = 'email' objects = RacchaiUserManager() class Meta: db_table = 'racchai_user' swappable = 'AUTH_USER_MODEL'
RacchaiUser
を作成すると同時に RacchaiUserManager
も作成していますが、ユーザーモデルをカスタマイズする際はこれらをセットで作成する必要があるということだけ覚えておいてもらえれば大丈夫です。
次は、Django が参照しているモデルクラスを差し替えます。racchai/settings.py にて以下を追記してください。
AUTH_USER_MODEL = 'racchai.RacchaiUser'
できましたか?
たったこれだけでカスタマイズしたUserモデルに差し替えることができています。マイグレーションして確認してみましょう。
$ ./manage.py makemigrations racchai Migrations for 'racchai': 0001_initial.py: - Create model RacchaiUser $ ./manage.py migrate Operations to perform: Synchronize unmigrated apps: staticfiles, messages Apply all migrations: admin, contenttypes, sessions, auth, racchai Synchronizing apps without migrations: Creating tables... Running deferred SQL... Installing custom SQL... Running migrations: Rendering model states... DONE Applying racchai.0001_initial... OK The following content types are stale and need to be deleted: auth | user Any objects related to these content types by a foreign key will also be deleted. Are you sure you want to delete these content types? If you're unsure, answer 'no'. Type 'yes' to continue, or 'no' to cancel: yes
マイグレーションは無事成功です。次は肝心のテーブル情報を見てみましょう。
$ mysql -uroot -p racchai mysql> desc racchai_user; +-------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | password | varchar(128) | NO | | NULL | | | last_login | datetime(6) | YES | | NULL | | | email | varchar(128) | NO | UNI | NULL | | | twitter_url | varchar(200) | NO | | NULL | | +-------------+--------------+------+-----+---------+----------------+
racchai_user
テーブルが作成されており、中身はさきほど RacchaiUser
クラスで定義したものになっていることがわかりますね。
動作確認
では実際にDjangoが参照するユーザーモデルが差し替わっているのか確認してみます。
ユーザー作成
createsuperuser
コマンドで racchai_user
テーブルにデータが登録されるかを確認してみます。
$ ./manage.py createsuperuser Email: test@racchai.com Password: test Password (again): test Superuser created successfully. $ mysql -uroot -p racchai -e "SELECT * FROM racchai_user" +----+-------------------------------------------------------------------------------+------------+---------------+-------------+ | id | password | last_login | email | twitter_url | +----+-------------------------------------------------------------------------------+------------+---------------+-------------+ | 1 | pbkdf2_sha256$20000$MlRFZRiDro4P$lIhUqpljqcqWDiaj0AnCTB8Y2NWBE5wempF31hY6jws= | NULL | test@racchai.com | | +----+-------------------------------------------------------------------------------+------------+---------------+-------------+
入りました!
認証
ユーザー認証の結果として得られるユーザーオブジェクトが差し替わっているかを確認します。
$ ./manage.py shell >>> from django.contrib.auth import authenticate >>> authenticate(email='test@racchai.com', password='test') <RacchaiUser: test@racchai.com>
無事認証結果が RacchaiUser
オブジェクトになってますね!
まとめ
今回はユーザーモデルをカスタマイズする方法についてご紹介してみました。
多少手間ではありますが、サービスに合ったユーザーモデルにカスタマイズするだけで開発効率が全然違ってくると思いますので、ぜひ試してみてください。