# 4.5 メニュー制御の実装(業務単位での公開制御とUX設計)
前回の記事では、CustomUser / Dept / Role を使った独自の権限管理について解説した。
今回はその情報を活用し、実際に メニューを業務単位で制御する仕組み と、
Vue Router とF5リロードの違いを考慮した設計のポイント を紹介する。
1. メニュー制御の基本方針
-
メニューは業務単位で定義
→ 「受注管理」「出荷予定」「作業指示」「原価管理」といった業務ごとにメニューを用意する -
公開範囲は部署コードで制御
→ 受注管理は営業と生産管理に、作業指示は製造に、原価は経理に…と柔軟に設定可能 -
段階的公開に対応
→ 本番切替時に「営業1課だけ先行公開、2課は後から追加」といった運用が可能
👉 この仕組みにより、不要なメニューを隠してUXを改善しつつ、運用の柔軟性も確保できる。
2. モデル設計
Menu モデル
メニューは「業務単位」で定義し、どの部署に公開するかを JSON で管理する。
# core/models/menu.py
from django.db import models
class Menu(models.Model):
name = models.CharField(max_length=100) # 業務名 (例: 受注管理)
url = models.CharField(max_length=255, blank=True)
parent = models.ForeignKey(
'self', null=True, blank=True, related_name='children', on_delete=models.CASCADE
)
sort_order = models.PositiveIntegerField(default=0)
icon = models.CharField(max_length=50, blank=True)
# 公開対象の部署コード(例: ["ALL"], ["SALES", "PROD"], ["ACC"])
allowed_dept_codes = models.JSONField(default=list)
def __str__(self):
return self.name
-
["ALL"]→ 全部署に公開 -
["SALES", "PROD"]→ 営業と生産管理にだけ公開 -
["ACC"]→ 経理にだけ公開
3. API 側での返却
ログイン後のメニューAPIで、ユーザーの所属部署コードと allowed_dept_codes を突き合わせ、
表示可能なメニューだけを返す。
返却例:
[
{ "name": "受注管理", "url": "/orders", "icon": "shopping-cart" },
{ "name": "出荷予定", "url": "/shipments", "icon": "truck" }
]
4. Vue 側での実装
Vue 側はシンプルに API が返したメニューを描画するだけ。
これにより Django 側でメニュー公開設定を変えれば、そのままフロントに反映される。
<template>
<nav>
<ul>
<li v-for="item in menuItems" :key="item.url">
<RouterLink :to="item.url">
<i :class="item.icon"></i> {{ item.name }}
</RouterLink>
</li>
</ul>
</nav>
</template>
<script setup>
import { ref, onMounted } from "vue";
import axios from "axios";
const menuItems = ref([]);
onMounted(async () => {
const res = await axios.get("/api/menus/");
menuItems.value = res.data;
});
</script>
5. Vue Router と F5 リロードの違い
ここが現場で一番ハマりやすいポイント。
-
メニュークリック時
Vue Router が制御 → SPA として画面が切り替わる -
F5リロード時
ブラウザが直接 Django にリクエスト → Vue Router は関与しない
結果、以下のような現象が起きることがある:
- クリック時は正常表示 → F5 すると 403 エラー
- 内部リンクから遷移するとOK → ブックマークから開くとNG
👉 業務システムではこの差を考慮し、
- API 側で認可を二重防御する
- Vue Router のルート設計と Django 側のルーティングを整合させる
といった工夫が欠かせない。
6. 運用で得られた効果
-
UX改善
→ 不要なメニューが消え、ユーザーが迷わなくなった -
運用効率化
→ メニューの公開/非公開は Django 側のマスタ更新で即反映可能 -
段階的リリースに対応
→ 部署ごとの本番切替を安全に進められる
7. AI活用のポイント
-
雛形生成に有効
Menu モデルのサンプルコードや Vue 側の描画処理は AI がすぐ出してくれるため、開発初期の効率は大きく上がった -
独自仕様はAI任せにできない
AI は「業務単位でメニューを定義し、部署ごとに公開制御する」という実プロジェクト特有の設計までは前提にしてくれない
→ 生成コードはあくまで叩き台であり、実仕様に合わせた調整は人間が行う前提 -
F5問題の指摘は期待できない
AI は「Vue RouterとF5リロードの挙動差による不具合」まで気づかないことが多い
→ 実際の利用動線を想定した検証は不可欠
まとめ
- メニューは 業務単位で定義し、部署ごとに公開範囲を設定
- 公開/非公開の切り替えは Django 側のマスタ更新だけで対応可能
- Vue 側は API が返すメニューを描画するだけで改修コストゼロ
- Vue Router とF5リロードの違いを意識し、ルーティングと認可は二重防御する
- AI は雛形生成には便利だが、独自仕様の考慮や挙動検証は人間の仕事
次回は、認証・権限の延長として 「JWT とセッション管理の実践」 に進む予定。
Discussion