【実例付】Django Userモデルをカスタマイズする方法

Django

(最終更新月:2022年3月)

✔このような方へ向けて書かれた記事となります

「デフォルトのユーザーモデルを変更したい!どんな方法があるの?」

「独自のユーザーモデルを作成する方法は?」

「ユーザーモデルを拡張したい。新たなフィールドを付け足す方法は?」

✔当記事を通じてお伝えすること

  • ユーザモデルとは?|一般的なモデルとの違いを解説
  • 独自のユーザーモデルを作成する方法を解説
  • ユーザーモデルを拡張する方法を解説

【著者プロフィール】

profile_icon
【Python歴】11年 x 【Django歴】10年
HP作成、社内システムの構築、コンサルティング

当ブログを通じて、Webアプリの書き方やアプリの公開方法までを解説しています。

☆日報アプリ「D-Repo」(デモ版)→こちら

※Djangoをベースに作成したアプリです。

☆便利ツールアプリ「Tool Station」→こちら

※Django REST frameworkとReactで作成しているアプリです。

上記のアプリでは、独自のユーザーモデルを作成し、「Eメールアドレスによる認証方法」へ変更しています。

ユーザモデルとは?|一般的なモデルとの違いを解説

ユーザーモデルとは?

ここでいうユーザーモデルとは、通常作成するモデルとは違い、Djangoアプリの認証で使われるモデルのことを言います。

セキュリティ性の高い認証システムは、Djangoの特長の一つです。

下記のコマンドでユーザーモデルクラスをインポートとし使用することが可能になります。

from django.contrib.auth.models import User

もしくは、カスタマイズしたユーザーモデルクラスを使用する場合などに備えて下記のコマンドも覚えておきましょう。

from django.contrib.auth import get_user_model
User = get_user_model()

get_user_modelメソッドを使うことで、アプリ内で実際に使われているユーザーモデルが変数「User」に格納されます。

私はユーザーモデルをカスタマイズすることが多いのでこちらの方法を使っています。

デフォルトのユーザーモデルを見てみる

デフォルトのユーザーモデルは、AbstractUserクラスを継承し、下記のフィールドが用意されています。

デフォルトユーザーのフィールド

  • username
  • first_name
  • last_name
  • email
  • is_staff
  • is_active
  • date_joined

認証で使われるフィールドはモデル内の「USER_NAME_FIELD」で下記のように指定されています。

USERNAME_FIELD = "username"

詳しくは、こちらのgithubページからご覧ください。

ユーザーモデルを変更したい時にできること2つ

こちらのユーザーモデルを変更したい場合、下記の2つの方法があります。

  1. 独自のユーザーモデルを作成する
  2. 外部キーを使って拡張や別のモデルと紐付けする

ポイントとしては、認証方法自体を変更したいのかどうかで上記のどちらを使うかが決まります。

独自ユーザーモデルを作成する

認証方法自体を変更したい場合はこちらの方法が適しています。

例えば、

  • Eメールアドレスでのログイン方法にしたい場合
  • IDによるログイン方法にしたい場合

など、独自の認証方法を構築したい場合に使用しましょう。

モデルクラス自体を書き換えるので、下記の方法より手間がかかります。

外部キーを使って拡張や紐付けをする

認証方法とは関係なく、ユーザーフィールドを追加したい場合特定のモデルにユーザーモデルを紐付けたい場合などはこちらが適しています。

あくまでも既存のユーザーモデルを拡張させるため、さほど複雑な処理はありません。

こちらもやり方は2通りです。

  1. OneToOneFieldを使う
  2. ForeignKeyを使う

OneToOneFieldを使うのは、ユーザーモデルと1対1の関係となるプロフィールクラスを定義する場面などが適しています。

ForeignKeyを使うのは、例えば「ツイートを発信したのがどのユーザーであるか」「注文をしたのがどのユーザーか」などユーザーと紐付けをしたい場合などが適しています。

以下では、①独自のユーザーモデルを作成する方法②外部キーを使ってユーザーモデルを拡張、ユーザーモデルと紐づける方法、のそれぞれ解説していきます。

独自のユーザーモデルを作成する方法を解説

まずは、①独自のユーザーモデルを作成する方法を解説します。

流れは下記のとおりです。

  1. ユーザーモデルクラスの属するappを作成し、設定する
  2. モデルクラスを作成する
  3. モデルクラスを操作するモデルマネジャークラスを作成する
  4. モデルクラスとモデルマネジャーを紐付ける
  5. データベースへ作成したモデルを書き込む
  6. Djangoのユーザー認証で使用することを宣言する

となります。

順に見ていきましょう。

ユーザー認証のためのアプリを作成・設定

「accounts」というappを作成、設定します。

ターミナルで下記の通りappを作成します。

python manage.py startapp accounts

settings.pyへ下記を追記します。

INSTALLED_APPS = [
    #....,
    #....,
    "accounts",
]

オリジナルのユーザーモデルを作成

AbstractBaseUser」クラスを継承して、新たなユーザーモデルクラスを作成します。

accounts > models.py

from django.db import models
from django.contrib.auth.models import AbstractBaseUser

class User(AbstractBaseuser):
    pass

継承元のインポートとオリジナルユーザーモデルクラス「User」を作成しました。

認証の為のユーザーモデルです。フィールドは下記の通り最低限とします。

  1. email
  2. active
  3. staff
  4. admin

id」「password」「last_login」の3つは既に備わっています。

オリジナルモデル「User」に上記のフィールドを追加していきます。

from django.db import models
from django.contrib.auth.models import AbstractBaseUser

class User(AbstractBaseuser):
    email = models.EmailField(
        verbose_name='Eメールアドレス',
        max_length=255,
        unique=True,
    )
    active = models.BooleanField(default=True)
    staff = models.BooleanField(default=False) 
    admin = models.BooleanField(default=False)

これだけでは、機能しません。

USERNAME_FIELD」や設定しておくべきメソッドもあるので下記のとおりとします。

class User(AbstractBaseUser):
    email = models.EmailField(
        verbose_name='Eメールアドレス',
        max_length=255,
        unique=True,
    )
    active = models.BooleanField(default=True)
    staff = models.BooleanField(default=False) 
    admin = models.BooleanField(default=False) 
   
    USERNAME_FIELD = 'email'

    def __str__(self):             
        return self.email

    def has_perm(self, perm, obj=None):
        return self.admin

    def has_module_perms(self, app_label):
        return self.admin

    @property
    def is_staff(self):
        return self.staff

    @property
    def is_admin(self):
        return self.admin

    @property
    def is_active(self):
        return self.active

ユーザーモデルクラスは以上です。

フィールドはご自由にカスタマイズしてください。ただし、このユーザーモデルでは最低限にとどめておくことをオススメします。

モデルは作りましたが、まだこのままでは不十分です。

ユーザーを操作するためのメソッド「create_user」等を作成する必要があります。

モデルマネジャーの定義と紐づけ

ユーザーモデルをカスタマイズする際は、モデルクラスのみならず、モデルマネジャーもカスタマイズする必要があります。

先ほど作成した「User」クラスの上に、「BaseUserManager」クラスを継承したマネジャークラスを作っていきます。

from django.db import models
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser

class UserManager(BaseUserManager):
    def create_user(self, email, password=None):
        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_staffuser(self, email, password):
        user = self.create_user(
            email,
            password=password,
        )
        user.staff = True
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password):
        user = self.create_user(
            email,
            password=password,
        )
        user.staff = True
        user.admin = True
        user.save(using=self._db)
        return user

ここでは、ユーザーを作成するメソッドを作っています。

モデルクラスとモデルマネジャーを紐付ける

どちらも完成しましたら、モデルマネジャー「UserManger」とモデル「User」を紐付けます。

下記をモデル内に追加します。

objects = UserManger()

参考までにこれまでのコード全体は下記の通りです。

accounts > models.py

from django.db import models
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser

class UserManager(BaseUserManager):
    def create_user(self, email, password=None):
        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_staffuser(self, email, password):
        user = self.create_user(
            email,
            password=password,
        )
        user.staff = True
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password):
        user = self.create_user(
            email,
            password=password,
        )
        user.staff = True
        user.admin = True
        user.save(using=self._db)
        return user

class User(AbstractBaseUser):
    email = models.EmailField(
        verbose_name='Eメールアドレス',
        max_length=255,
        unique=True,
    )
    active = models.BooleanField(default=True)
    staff = models.BooleanField(default=False) 
    admin = models.BooleanField(default=False) 
   
    USERNAME_FIELD = 'email'

    objects = UserManager()

    def __str__(self):             
        return self.email

    def has_perm(self, perm, obj=None):
        return self.admin

    def has_module_perms(self, app_label):
        return self.admin

    @property
    def is_staff(self):
        return self.staff

    @property
    def is_admin(self):
        return self.admin

    @property
    def is_active(self):
        return self.active

マイグレーションの実行

以上でユーザーモデルのコードは完成です。

データベースへモデルを書き込んでいきます。

$ python manage.py makemigrations
Migrations for 'accounts':
  accounts/migrations/0001_initial.py
    - Create model User

$ python manage.py migrate
Operations to perform:
  Apply all migrations: accounts, admin, auth, contenttypes, nippo, sessions
Running migrations:
  Applying accounts.0001_initial... OK

エラー等がなければ次へ進みましょう。

作成したモデルクラスをユーザー認証用として使う

データベースへの書き込みも終わりましたが、今のままでは、作成した「User」モデルは単なる一モデルクラスでしかありません。

実際に認証用として使うことを宣言する必要があります。

settings.pyで下記を追記します。

AUTH_USER_MODEL = 'accounts.User'

settings.pyに変更を加えたので、再度migrateのみで良いので実行しましょう

$ python manage.py migrate

エラーが出なければ、無事完了です。

最後に確認の意味も含めてスーパーユーザーを作ります。

【確認】スーパーユーザーを作成しよう!

ターミナルでスーパーユーザー作成の為のコマンドを入力します。

$ python manage.py createsuperuser
Eメールアドレス:

通常だと、「ユーザー名」から始まりますがオリジナルユーザーモデルで指定した通り「Eメールアドレス」が認証用で使われている事がわかります。

ログイン画面もこの通りです。

以上で独自のユーザーモデルクラスは完成しました。

ただこのまま進むと、Adminページでうまく操作ができません。

続きは下記の記事で解説をしています。

ユーザーモデルを拡張する方法を解説

主に使用する外部キーは下記の2つです。

  1. OneToOneField
  2. ForeignKey

これらのコードは複雑ではありませんので例をご覧いただきながら解説します。

OneToOneFieldを使う

OneToOneFieldを使ったサンプルです。

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    username = models.CharField(max_length=100, verbose_name="ユーザー名")
    department = models.CharField(max_length=100, blank=True, null=True, verbose_name="部署")
    phone_number = models.IntegerField(blank=True, null=True, verbose_name="携帯番号")
    gender = models.CharField(max_length=1, choices=[(None, "--"), ("m", "男性"), ("f", "女性")], default=None, verbose_name="性別", blank=True, null=True)
    birthday = models.DateField(blank=True, null=True, verbose_name="生年月日")

    def __str__(self):
        return self.username

詳しくはこちらで解説しています↓

ForeignKeyを使う

ForeignKeyを使ったサンプルです。

from django.db import models
from django.contrib.auth import get_user, get_user_model

User = get_user_model()

class NippoModel(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=100, verbose_name="タイトル")
    content = models.TextField(max_length=1000, verbose_name="内容")
    timestamp = models.DateTimeField(auto_now_add=True)

詳しくはこちらで解説しています↓

まとめ

当記事の内容をまとめます。

ユーザーモデルとは、Djangoアプリの認証で使われるモデルのことを言います。

Djangoにはユーザーモデルがデフォルトで用意されておりそのまま使うことも可能です。

ただ、作成しているアプリによっては変更する必要もあります。

変更する方法は下記の通りです。

  1. 独自のユーザーモデルを作成する
  2. 外部キーを使って拡張や別のモデルと紐付けする

それぞれの方法については上記にございますので必要な時にいつでもご覧ください。

また、このまま進んでもAdminページでうまく操作ができません。

続きは下記の記事で解説をしています。

✔ウェブアプリを公開したい方へのおすすめ記事

【保存版】Apache WebサーバーでDjangoアプリを公開
Djangoが公開できる月500円~のレンタルサーバー
【初心者向け】ムームードメインで独自ドメインを取得する3ステップ
【実体験】マイIPの使い方を解説|固定IPアドレスを取得・設定する

✔当ブログは以下のような方に向けて書かれています

「Djangoでのアプリ開発を学びたい!」

「Djangoで開発したアプリをWebで公開するにはどうするの?」

✔当ブログ掲載の記事

  • Djangoで作る日報アプリ開発
  • WebアプリをWeb上に公開する方法
  • Webアプリ開発に必要なそのほかの情報
【Django】チュートリアル|日報アプリの開発から公開まで
Djangoのチュートリアルをお探しですか?具体的に「手を動かして作ってみたい!」という方へ向けて、誰でもできる簡易的な日報アプリの開発を通じて、Djangoの様々な機能に触れていくシリーズとなっています。PythonでWebアプリを作りたい方、必見の記事となります!

公式LINEも始めました。記事更新についてや、当ブログ内の人気記事などの情報を定期的に配信しています。

友だち追加

ITCブログにご協力いただける方は、以下もご検討いただけると嬉しいです。

ITCに投げ銭をする

タイトルとURLをコピーしました