# 4.4 独自ロールモデルによる権限管理
前回の記事では Django 標準の権限機能(ユーザー・グループ・パーミッション)を紹介した。
しかし業務システムでは、モデル単位の CRUD 権限だけでは表現できない要件が多い。
実際のプロジェクトでは、Django 標準の権限は使わず、独自のユーザー・部署・ロール管理モデル を設計して運用している。
1. 標準の権限機能を使わなかった理由
-
モデル単位の権限粒度では業務要件を表現できない
- 例: 「受注は閲覧できるが承認はできない」
-
管理画面での権限設定が煩雑すぎる
-
部署や組織階層に紐づく権限設計が難しい
2. 独自設計の全体像
以下のモデルを中心に構成した。
- CustomUser: 拡張ユーザーモデル
- Dept: 部署(親子関係を持ち、階層を表現できる)
- Role: ロール(営業担当、営業部長、管理者などの役割)
- UserDept: ユーザーと部署の関連
- UserRole: ユーザーとロールの関連
これにより「ユーザー × 部署 × ロール」という形で柔軟な権限管理を行う。
3. モデル設計例
CustomUser
Django のユーザーモデルを拡張。
社員番号やフルネームなど業務で必須の属性を追加。
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
employee_code = models.CharField(max_length=20, unique=True)
full_name = models.CharField(max_length=100)
Dept(部署)
部署は階層構造を持つように設計。
親部署を持つことで「本社 → 営業部 → 第一営業課」のようにツリー構造を表現できる。
class Dept(models.Model):
code = models.CharField(max_length=20, unique=True)
name = models.CharField(max_length=100)
parent = models.ForeignKey(
"self", null=True, blank=True, on_delete=models.CASCADE, related_name="children"
)
def __str__(self):
return self.name
Role(ロール)
役割を定義するモデル。
例: sales
, manager
, admin
class Role(models.Model):
code = models.CharField(max_length=50, unique=True)
name = models.CharField(max_length=100)
def __str__(self):
return self.name
UserDept(ユーザー × 部署)
1人のユーザーが複数の部署に所属できるように設計。
class UserDept(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
dept = models.ForeignKey(Dept, on_delete=models.CASCADE)
UserRole(ユーザー × ロール)
ユーザーに複数のロールを付与可能。
class UserRole(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
role = models.ForeignKey(Role, on_delete=models.CASCADE)
4. この構成でできること
- 部署ごとにロールを割り当てられる
→ 「営業部長は承認できるが、営業担当はできない」 - ユーザーが複数部署に所属可能
→ 「営業部と開発部の兼務」も表現できる - 階層構造を持つ部署をたどることで
→ 「部長以上は下位部署の承認も可能」などの要件を表現可能
5. API とフロントでの活用
API 側(auth_status の返却例)
ログイン後の auth_status
API で以下の情報を返す。
{
"username": "taro",
"full_name": "山田 太郎",
"departments": [
{ "code": "001", "name": "営業部" },
{ "code": "002", "name": "開発部" }
],
"roles": ["sales", "manager"]
}
Vue 側での使い方
- ログイン成功時に
auth_status
を呼び出し、結果を Pinia / Vuex のストア に保持する - 画面遷移時にストアの情報を参照し、権限に応じて UI を制御する
例:
// store/auth.js
import { defineStore } from "pinia";
import axios from "axios";
export const useAuthStore = defineStore("auth", {
state: () => ({
username: null,
fullName: null,
roles: [],
departments: [],
}),
actions: {
async fetchAuthStatus() {
const res = await axios.get("/api/auth/status/");
this.username = res.data.username;
this.fullName = res.data.full_name;
this.roles = res.data.roles;
this.departments = res.data.departments;
},
hasRole(role) {
return this.roles.includes(role);
}
}
});
メニュー表示例
<button v-if="auth.hasRole('manager')">承認メニュー</button>
<button v-if="auth.hasRole('sales')">受注入力</button>
import { useAuthStore } from "@/stores/auth";
const auth = useAuthStore();
API 側での利用(権限チェック)
バックエンドの各 API でもロールを参照して権限チェックを行う。
フロントでボタンを隠すだけでは不十分なので、API 側で「二重防御」する。
from django.http import JsonResponse
def require_role(user, role):
return user.userrole_set.filter(role__code=role).exists()
def approve_order(request):
if not require_role(request.user, "manager"):
return JsonResponse({"error": "承認権限がありません"}, status=403)
# 承認処理...
6. メリットと課題
メリット
- 業務要件に沿った粒度で柔軟に権限設計できる
- 部署の階層構造を反映可能
- Vue 側でメニュー制御しやすい
課題
- Django 標準の Permission 機能は活用できない
- 権限 UI も自前で構築する必要がある
- 設計を誤ると管理が複雑化する
7. AI活用のポイント
独自のロールモデルを導入すると、AI が生成するコードに対して次の注意点がある。
-
AIは独自仕様を覚えていない
ChatGPT 等にコードを生成させる場合、毎回「このプロジェクトでは CustomUser / Dept / Role / UserDept / UserRole を使っている」と伝えないと、標準のPermission
やGroup
前提で回答してくることがある。
→ 無駄なやり取りが発生しがちなので、「今このアプリではこういう権限管理をしている」と 適宜リマインドすることが重要。 -
ロールの扱い方に揺らぎがある
- 会社の組織上のロール(部長、課長など)
- 業務上のロール(受注承認担当、棚卸管理者など)
これを同列で扱うか、別のモデルに分けるかは設計判断が必要。
私のプロジェクトでは 同列に扱う 方針を採用したが、運用や管理者の慣れによって分けるケースもある。
-
AIを活用するコツ
- 「ユーザー × 部署 × ロール」という設計を毎回提示してコードを生成させる
- Vue 側のメニュー制御や Django 側の二重防御ロジックもまとめて依頼すると精度が高まる
- 「承認は部長以上」「担当者ロールは部署ごとに割り当て」など、業務要件を具体的に書いてリクエストする と想定通りのコードが得やすい
👉 要するに、AIは便利なコーディング補助になるが、プロジェクト特有の独自仕様を前提に入れてやらないと誤解する。権限管理のようなカスタム要件は、その点を踏まえて活用するのが実践的。
まとめ
- Django 標準の権限はシンプルだが、業務システムには不十分
- CustomUser / Dept / Role / UserDept / UserRole を中心に自前設計した
- 部署階層とロールを組み合わせることで、実際の運用に耐えられる柔軟な管理が可能
- auth_status API → Vue のストア → UI 制御 という流れで、ユーザー体験も自然に
- API 側でも権限チェックを行い、二重防御を徹底する
- AI を活用する際は「このアプリの独自設計」を逐一伝えることが重要
- ロールの扱い(組織ロールと業務ロールを分けるか同列にするか)は運用ポリシー次第
次回は、この権限情報を用いた メニュー制御の実装 について紹介する。
Discussion