Django Admin カスタムユーザーの作成方法

◆ Live配信スケジュール ◆
サイオステクノロジーでは、Microsoft MVPの武井による「わかりみの深いシリーズ」など、定期的なLive配信を行っています。
⇒ 詳細スケジュールはこちらから
⇒ 見逃してしまった方はYoutubeチャンネルをご覧ください
【5/21開催】Azure OpenAI ServiceによるRAG実装ガイドを公開しました
生成AIを活用したユースケースで最も一番熱いと言われているRAGの実装ガイドを公開しました。そのガイドの紹介をおこなうイベントです!!
https://tech-lab.connpass.com/event/315703/

Userモデルをカスタマイズ

Django Adminでは管理サイトにログインするユーザーの管理などを行えるUserモデルがデフォルトで定義されています。しかし、デフォルトのUserモデルではカスタマイズが行うことができず、プロジェクト開始後に要件の変更があったとしてもUserモデルの拡張を行うことができません。そのためプロジェクト初期の段階ではデフォルトモデルで十分な場合でも、カスタムユーザーモデルのセットアップをマイグレーションを行う前に設定することがDjangoの公式ドキュメントでも推奨されています。

参考 : Django

Userの関係について

ここでカスタムユーザーを作成するために必要な要素について理解しやすくするために、デフォルトのUserモデルの継承について整理します。Userの継承は以下の図の様になってます。

実際にカスタムユーザーを作成する場合、AbstractUserを継承する方法を、AbstractBaseUserとPermissionsMixinの2つを継承する方法があります。

デフォルトのものにフィールドやメソッドを付け加えていきたいなら、AbstractUserを継承してカスタムユーザーを作成しましょう

AbstractUser周りで継承されているフィールドが必要なければAbstractBaseUserとPermissionsMixinを継承してカスタムユーザーを作成しましょう。

今回はより複雑なAbstractBaseUserとPermissionsMixinを継承する方法を元に解説していきます。

カスタムユーザーを作成する

ここからは実際にカスタムユーザーを作成する手順について紹介します。

カスタムユーザー用のアプリケーションを作成する

カスタムユーザーモデルの定義を行うアプリケーションauthorizationの作成をします。

python manage.py startapp authorization

作成が完了したら、setting.pyのINSTALL_APPSに作成したアプリであるauthorizationの追加を行います。

INSTALLED_APPS = [
  "django.contrib.admin",
  "django.contrib.auth",
  "django.contrib.contenttypes",
  "django.contrib.sessions",
  "django.contrib.messages",
  "django.contrib.staticfiles",
  "authorization",
]

AbstractBaseUserとPermissionsMixinを継承したCustomUserの作成を行う

作成したアプリケーションauthorizationのmodel.pyにCustomUserモデルを以下のように定義します。

from django.db import models
from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.models import BaseUserManager

class CustomUserManager(BaseUserManager):
  def get_by_natural_key(self, username):
    return self.get(username=username)

  def create_superuser(self, username, 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(username, password, **extra_fields)

  def _create_user(self, username, password=None, **extra_fields):
    if not username:
      raise ValueError('The Username field must be set')
    user = self.model(username=username, **extra_fields)
    user.set_password(password)
    user.save(using=self._db)
    return user

class CustomUser(AbstractBaseUser, PermissionsMixin):
  username = models.CharField(verbose_name="ユーザーネーム", unique=True, max_length=100)
  is_staff = models.BooleanField(default=False)
  objects = CustomUserManager()

  USERNAME_FIELD = 'username'

CustomUserクラス

フィールドの定義

  username = models.CharField(unique=True,max_length=100)
  is_staff = models.BooleanField(default=False)

認証時に使用するフィールドとしてCharField型のusernameと管理サイトにログイン可能を判別するためのフィールドとしてBooleanField型のis_staffを定義しています。注意点としては、is_staffはAbstractBaseUserとPermissionsMixinにて扱われていませんが、定義しない場合、管理サイトにログインできなくなってしまうので、管理サイトを作成する場合には必ず定義するようにしましょう。

USERNAME_FIELDの指定

  USERNAME_FIELD = 'username'

USERNAME_FIELD属性を利用することで、認証時に使用するフィールドを指定することができます。このとき使用するフィールドにはuniqueオプションを指定し、データベース全体で一意である必要があります。今回の例ではUSERNAME_FIELDにusernameというフィールドを使用していますが、uniqueなフィールドであれば、username以外のフィールドを指定して、認証時に使用することもできます。

使用するマネージャーの指定

  objects = CustomUserManager()

CustomUserManagerクラスのインスタンスを作成し、カスタムユーザーモデルでの、データベースとのやり取りやクエリの実行、データの作成、更新、削除などの操作を行うマネージャーオブジェクトの作成を行います。objectsという名前は、Djangoのソースコード内でマネージャーを指定する際に使用される標準的な名前になっています。マネージャーが必要となる点はAbstractBaseUserとPermissionsMixinを継承する際に見落しがちな点なのでご注意ください。

CustomUserManagerクラス

CustomUserで使用するマネージャーのクラスを作成します。管理サイトにログインできるユーザーを作成するためにはcreatesuperuserコマンドを実行できるようにする必要があるため、少なくとも_create_userメソッドとcreate_superuserメソッドを作成する必要があります。

_create_userメソッドの作成

def _create_user(self, username, password=None, **extra_fields):
  if not username:
    raise ValueError('The Username field must be set')
  user = self.model(username=username, **extra_fields)
  user.set_password(password)
  user.save(using=self._db)
  return user

新しいユーザーを作成するときに使用するメソッドです。このメソッドは後述するcreate_superuserメソッドで使用するため、作成する必要があります。

create_superuserメソッドの作成

def create_superuser(self, username, 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(username, password, **extra_fields)

新しいスーパーユーザーを作成するときに使用するメソッドです。createsuperuserコマンドを実行した場合には、is_staffとis_superuserをTrueにしてユーザーの作成を行います。

このメソッドがない場合、createsuperuserコマンドが実行できず、スーパーユーザーの作成が行えないため、管理サイトにログインすることができなくなります。

管理画面にCustomUserモデルを表示する

authorizationのadmin.pyに以下の以下のコードを記述します。

from django.contrib import admin
from .models import CustomUser

class CustomUserAdmin(admin.ModelAdmin):
  list_display = (
    "username",
    "is_staff",
    "is_superuser",
  )

  fieldsets = (
    ("基本情報", {"fields": ("username", "password")}),
    (
      "権限情報",
      {
        "fields": (
          "is_staff",
          "is_superuser",
          "groups",
          "user_permissions",
        ),
      },
    ),
    ("日時情報" , {"fields": ["last_login"]}),
  )

認証に使用するモデルとしてCustomUserモデルを指定する

setting.pyのAUTH_USER_MODELにCustomUserモデルを指定して、認証に使用するモデルを変更します。

AUTH_USER_MODEL = 'authorization.CustomUser'

モデルのマイグレーションを行う

マイグレーションコマンドを実行し、変更したモデルを反映します。

python manage.py makemigrations
python manage.py migrate

Tips

以前の認証に使用したモデルでマイグレーションを行っていると、エラーが起こります。そのような場合には、各アプリケーションのmigrations以下にある__init__.py以外のファイルの削除を行ったあと、dbの削除を行いましょう。dbの削除はデフォルトの状態であれば、db.sqlite3を削除することで実行できます。こちらの方法を使用すると、今まで入力してきたデータが無くなるため、カスタムユーザーモデルのセットアップをマイグレーションを行う前に設定することがDjangoの公式ドキュメントで推奨されているのだと思われます。先にカスタムユーザーを作成したあとであれば、フィールドの追加等のカスタマイズも可能なためカスタムユーザーの作成は優先して行いましょう。

スーパーユーザーを作成する

createsuperuserコマンドを実行して作成したカスタムユーザーモデルを元に管理者ユーザーが作成できることを確認しましょう。

python manage.py createsuperuser
ユーザーネーム: admin
Password:
Password (again):
Superuser created successfully.

おまけ : AbstractUserを継承してカスタムユーザーを作成する場合

作成したアプリケーションauthorizationのmodel.pyにCustomUserモデルを以下のように定義します。

class CustomUser(AbstractUser):
  first_name = None
  last_name = None
  full_name = models.CharField(max_length=100)

  class Meta:
      db_table = 'custom_user'

この方法の場合、AbstractBaseUserとPermissionsMixinやAbstractUserに存在しているフィールドについてNoneと指定することで、そのフィールドをモデルで扱わなくすることができます。

マネージャーについてはAbstractUserで宣言されているため、マネージャーのカスタムが必要ないのであれば用意する必要はありません。

USERNAME_FIELDの使用も可能で、emailなどを識別用のフィールドとして扱うこともできます。

作成したアプリケーションのディレクトリ構造

.
├── authorization
│   ├── __init__.py
│   ├── __pycache__
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── config
│   ├── __init__.py
│   ├── __pycache__
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── db.sqlite3
└── manage.py

終わりに

今回はDjango Adminでカスタムユーザーを導入する方法について紹介しました。カスタムユーザーを導入するにはデフォルトのユーザーモデルの継承関係などを知らないと理解しにくく、難しい内容だったと思います。

他の記事でもDjango Adminについての解説をしているのでよければ合わせて御覧ください。

アバター画像
About 遠藤 4 Articles
情報系の学部を卒業後、2023年にサイオステクノロジーに入社しました。アプリチームに所属しています。vimキーバインドが好きです。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。


ご覧いただきありがとうございます。
ブログの最新情報はSNSでも発信しております。
ぜひTwitterのフォロー&Facebookページにいいねをお願い致します!



>> 雑誌等の執筆依頼を受付しております。
   ご希望の方はお気軽にお問い合わせください!

Be the first to comment

Leave a Reply

Your email address will not be published.


*


質問はこちら 閉じる