# 6.3 accounts アプリの作成とカスタムユーザモデル
今回は ユーザ管理を担う accounts アプリ を作成する。
業務システムでは「ユーザ・部署・ロール」は必ず出てくる要素なので、最初から専用アプリに切り出しておくのが望ましい。
1. アプリ作成
cd backend
python manage.py startapp accounts
👉 これで accounts/
ディレクトリが作成される。
この中にユーザ関連のモデルをすべてまとめる。
2. モデル定義
2.1 User(カスタムユーザ)
# accounts/models/user.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
full_name = models.CharField(max_length=100, blank=True)
def __str__(self):
return self.username
- Django 標準のユーザモデル
AbstractUser
を継承 -
full_name
を追加(業務ではフルネーム管理が必須) -
__str__
を username にしておくと管理画面で見やすい
2.2 部署モデル
# accounts/models/dept.py
from django.db import models
class Dept(models.Model):
code = models.CharField(max_length=20, unique=True)
name = models.CharField(max_length=100)
def __str__(self):
return f"{self.code} {self.name}"
📌 解説
- このモデルでは Django が自動的に
id
(数値の主キー)を付与しており、実際の主キーはid
-
code
は 業務上の一意な識別子 として利用する想定(unique 制約あり) - 実務的には「部署コードで一意に管理する」ケースが多いが、DB のキーは数値 ID に任せたほうが扱いやすい場面も多い
→ M2M 関係や外部キー参照で bigint が自然に使われるため、クエリの型不一致を避けやすい - もし「部署コードそのものを主キーにしたい」なら
primary_key=True
を付けてid
を消す方法もあるが、今回は扱いやすさ重視で数値 ID を主キーのままにしている
💡 補足
本来の業務システムでは「部署の階層構造(親部署を持つ)」をモデル化することが多い。
例:営業本部 → 東京営業部 → 第一課
ただし、今の教材段階ではまずシンプルに部署単体だけを扱うことにして、親子関係は導入していない。
後から必要になったら parent = models.ForeignKey("self", ...)
を追加すれば階層構造を表現できる。
2.3 ロールモデル
# accounts/models/role.py
from django.db import models
class Role(models.Model):
code = models.CharField(max_length=20, unique=True)
name = models.CharField(max_length=100)
def __str__(self):
return self.name
📌 解説
部署と同様に 数値 ID を主キーにしつつ、code を業務キーに使う 形で進める
💡 補足
ロール設計はシステムごとに幅がある。
単純に「画面ごとの権限」だけでなく、「部署ごとの権限」や「承認フローのステップ」を兼ねる場合もある。
今の段階ではシンプルに code
と name
のみで進める。
2.4 ユーザと部署の紐付け
# accounts/models/user_dept.py
from django.db import models
from .user import User
from .dept import Dept
class UserDept(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
dept = models.ForeignKey(
Dept, to_field="code", db_column="dept_code", on_delete=models.CASCADE
)
is_primary = models.BooleanField(default=False) # 主所属フラグ
assigned_at = models.DateTimeField(auto_now_add=True)
class Meta:
unique_together = ("user", "dept")
📌 解説
-
中間テーブルを明示的に定義し、ユーザと部署を紐付け
-
to_field="code"
により 部署コードで参照する設計- 例:
sales
/tokyo
のように人間が読める文字列キー - 組織変更などで id が変わっても code が安定していれば参照関係が崩れにくい
- 例:
-
is_primary
で「主所属 / 兼務」を区別可能 -
unique_together
で同じ組み合わせを重複登録できないよう制約
💡 補足
一般的な実装では、以下のように id(数値主キー)を参照する方が多い。
dept = models.ForeignKey(Dept, on_delete=models.CASCADE)
この場合、DB 的には bigint 同士で結合されるので効率的だし、Django の外部キー周りとも相性が良い。
to_field="code"
を使うのは、コードを安定したキーとして扱いたいとき。
自分が関わったシステムではこの方式だったので、今回はその形で書いている。
2.5 ユーザとロールの紐付け
# accounts/models/user_role.py
from django.db import models
from .user import User
from .role import Role
class UserRole(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
role = models.ForeignKey(
Role, to_field="code", db_column="role_code", on_delete=models.CASCADE
)
granted_at = models.DateTimeField(auto_now_add=True)
class Meta:
unique_together = ("user", "role")
📌 解説
- ロールも同様に コード基準で参照している
-
granted_at
で「いつロールが付与されたか」を記録可能
💡 補足
こちらも実務では id 外部キーで持つ方が一般的。
2.6 モデル集約
# accounts/models/__init__.py
from .user import User
from .dept import Dept
from .role import Role
from .user_dept import UserDept
from .user_role import UserRole
👉 これにより外部からは
from accounts.models import User, Dept, Role
のように一括で呼び出せる。
3. settings.py の修正
INSTALLED_APPS = [
...,
"accounts",
]
AUTH_USER_MODEL = "accounts.User"
-
INSTALLED_APPS
に追加 - カスタムユーザを使うために
AUTH_USER_MODEL
を指定
👉 これは プロジェクト開始時に必須。途中変更はできない。
4. 管理画面の設定
# accounts/admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .models import User, Dept, Role, UserDept, UserRole
@admin.register(User)
class UserAdmin(BaseUserAdmin):
fieldsets = BaseUserAdmin.fieldsets + (
("業務情報", {"fields": ("full_name",)}),
)
admin.site.register(Dept)
admin.site.register(Role)
admin.site.register(UserDept)
admin.site.register(UserRole)
-
UserAdmin
を拡張し、full_name
を管理画面で編集可能にした - 部署・ロール・中間テーブルも登録
5. マイグレーション
python manage.py makemigrations accounts
python manage.py migrate
👉 これで DB に accounts_user
, accounts_dept
, accounts_role
, accounts_userdept
, accounts_userrole
テーブルが作成される。
6. 管理ユーザーの作成
python manage.py createsuperuser
👉 メールアドレスやパスワードを入力し、admin にログイン可能なユーザを作る。
7. 動作確認
-
開発サーバーを起動
python manage.py runserver
-
管理画面にアクセス
http://127.0.0.1:8000/admin/
-
部署・ロールを登録
- 部署:
A001 営業一課
- 部署:
M001 製造部
- ロール:
order_approve
- ロール:
asset_manager
- 部署:
-
ユーザを作成し、部署とロールを割り当てる
👉 これで「ユーザがどの部署に所属し、どのロールを持つか」が管理可能になった。
今回のゴール
- accounts アプリを作成し、ユーザ管理を分離
- AbstractUser 継承でカスタムユーザモデルを定義
- 部署(Dept)、ロール(Role)、紐付けモデル(UserDept / UserRole)を実装
- 紐付けは 部署コード / ロールコード基準 で管理
- マイグレーション & superuser 作成 を完了し、admin にログインできた
- 管理画面からユーザ・部署・ロールを操作可能になった
次の展開
次は 6.4 ログイン API の実装 に進む。
今回のユーザモデルを使い、ログイン時に部署・ロールを返す API を構築する。
Discussion