概要
- 以下の記事で、Auth機能とMessageフレームワークを使ってユーザーごとにアクセス権限を設定する手順を紹介しました。今回は、アクセス権限を設定し、なおかつ、ログインユーザーにアクセス権のあるボタンのみを表示する方法を紹介します。
- 前回の記事:
前提
- 前回実施した続きなので、以下は実施済みの前提です。
- Auth機能でGroup作成&User追加
- メッセージフレームワークを利用するための
views
設定やルーティング設定
実施方法
- カスタムテンプレートタグを使って「
group_id
に基づいてボタンの表示・非表示を制御する」ことを行います。- ①カスタムテンプレートタグの作成
- ②HTMLテンプレートの編集
①カスタムテンプレートタグの作成
- カスタムテンプレートタグとは、
{% if ... %}
など元から使えるビルトイン・テンプレートタグと違って、自分で独自に定義して処理や関数を呼び出すことができるタグです。 - まずは、アプリ内に
templatetags
ディレクトリを作成します。 -
templatetags
ディレクトリ内に__init__.py
ファイルを作成(これは空のまま)。 -
templatetags
ディレクトリ内にgroup_tags.py
ファイルを作成。以下のように記載します。
group_tags.py
from django import template
register = template.Library()
@register.filter
def has_group(user, group_id):
return user.groups.filter(id=group_id).exists()
-
has_group
というフィルターを実装しました。このフィルターは、ユーザーが指定したグループに所属しているかどうかを判定し、結果を返します。 -
@register.filter
は、カスタムテンプレートフィルタを登録するデコレータです。
②HTMLテンプレートの編集
- ボタン制御を行いたいテンプレートを編集します。
- まず、
group_tags
モジュールをテンプレートで呼び出すため、先頭に以下を記載します。
home.html
{% load group_tags %}
- 次に、例えば以下のアクセス制御をしたいとします。
-
group_id = 1
の人にはボタン「権限レベル1のボタン」を表示し、それ以外は表示しない -
group_id = 2
の人にはボタン「権限レベル1のボタン」「権限レベル2のボタン」を表示し、それ以外は表示しない
-
- 上記の場合、以下のようにテンプレートに加えます。
home.html
{% if request.user|has_group:"1" or request.user|has_group:"2" %}
<div class="card-wrapper">
<div>
<button class="button color">
<a class = "button name" href="{% url 'level1' %}">権限レベル1のボタン</a>
</button>
</div>
</div>
{% endif %}
{% if request.user|has_group:"2" %}
<div class="card-wrapper">
<div>
<button class="button color">
<a class = "button name" href="{% url 'level2' %}">権限レベル2のボタン</a>
</button>
</div>
</div>
{% endif %}
- これにより、
has_group
というカスタムフィルターを使用して、group_id
に基づいたボタンの表示・非表示を制御することができました。
TemplateSyntaxError at...
エラーについて
- 以下のエラーが出た場合、正しいディレクトリにカスタムのテンプレートタグが登録されていない可能性があります。
templatetags
は通常アプリケーションのディレクトリ内に作成します。正しい場所にあるかチェックしましょう。
TemplateSyntaxError at /home/
'group_tags' is not a registered tag library. Must be one of:
ホワイトリスト方式・ブラックリスト方式
- 以上、ボタンの表示・非表示を行うことができました。
-
or
を使うことで複数のグループのアクセス制御ができますし、この方法だと割と簡潔に実装できます。 - 仮に、アクセス権のないURLを直打ちで打つと、前回の記事で実装したメッセージが表示されます。
-
- カスタムテンプレートを使っているのは、Djangoのテンプレートエンジンでは、直接条件文を使用して表示・非表示を制御することができないためです。他にもっと良い方法がある、ということがあればぜひ教えてください。
- セキュリティ対策の考え方には、ホワイトリスト方式・ブラックリスト方式という考え方があります。どちらの方が好ましいかは、サイトのセキュリティ要件や運用方針に合わせて判断すると良いと思います。
- ホワイトリスト方式:「安全な対象」を定義 = 承認するユーザー(グループ)を決める
- ブラックリスト方式:「危険な対象」を定義 = 拒否するユーザー(グループ)を決める
- 参考:ホワイトリスト、ブラックリストって何ですか?