21.

Django テンプレートでログイン判定する方法(is_authenticated / is_staff / グループ判定)

編集
この記事の要点
  • {% if user.is_authenticated %} でログイン済か判定するのが基本
  • request をテンプレートに渡すのは django.template.context_processors.request、ユーザーは auth プロセッサ
  • 管理者判定: user.is_staff / スーパーユーザー: user.is_superuser
  • グループ判定: {% if user.groups.all|length > 0 %} または カスタムテンプレートタグ
  • ログイン強制はテンプレート側ではなく view 側の @login_required デコレータで
  • JSON API では request.user.is_authenticated を view で判定し、403 を返す

基本: is_authenticated

Django で「ログインしているか」を判定する最もシンプルな方法:

{# templates/base.html #}

user 変数はテンプレート内で自動的に使えます(後述の context processor が設定されている場合)。

context_processors の確認

テンプレートから userrequest を参照できるのは、Django のauth コンテキストプロセッサが有効だからです:

# settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',     # ← request 変数
                'django.contrib.auth.context_processors.auth',     # ← user / perms 変数
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

auth プロセッサが入っていれば、すべてのテンプレートで {{ user }}{{ perms }} が使えます。

権限別の表示制御

{% if user.is_authenticated %}
    {# 一般会員向け #}
    マイページ

    {% if user.is_staff %}
        {# スタッフ向け(管理画面アクセス可) #}
        管理画面
    {% endif %}

    {% if user.is_superuser %}
        {# スーパーユーザー専用 #}
        システム設定
    {% endif %}

    {% if user.email_verified %}
        {# 自前で追加した属性も普通に使える #}
        認証済
    {% endif %}
{% else %}
    ログイン
{% endif %}

パーミッション判定: {% if perms.app.action %}

Django の django.contrib.auth のパーミッションシステムに沿うなら:

{# polls アプリの change_poll 権限を持っているか #}
{% if perms.polls.change_poll %}
    編集
{% endif %}

{# 複数 #}
{% if perms.polls.add_poll and perms.polls.delete_poll %}
    
{% endif %}

グループ判定

「特定のグループに所属しているか」をテンプレートで判定したい場合:

# myapp/templatetags/auth_extras.py
from django import template

register = template.Library()

@register.filter(name='has_group')
def has_group(user, group_name):
    return user.groups.filter(name=group_name).exists()
{% load auth_extras %}

{% if user|has_group:"editors" %}
    編集者ダッシュボード
{% endif %}

{% if user|has_group:"premium" %}
    プレミアムコンテンツ
{% endif %}

テンプレートタグでより複雑な判定

# myapp/templatetags/auth_extras.py
from django import template

register = template.Library()

@register.simple_tag(takes_context=True)
def can_edit(context, obj):
    """記事の作者 or staff なら True"""
    request = context['request']
    user = request.user
    if not user.is_authenticated:
        return False
    if user.is_staff:
        return True
    return obj.author_id == user.id
{% load auth_extras %}

{% can_edit article as user_can_edit %}
{% if user_can_edit %}
    編集
{% endif %}

ログイン強制は view 側で

テンプレートで条件分岐するだけではセキュリティ的に不十分です。データを返さないようにするには view 側で:

from django.contrib.auth.decorators import login_required, permission_required, user_passes_test

@login_required
def mypage(request):
    return render(request, 'mypage.html')

# ログインしてかつパーミッションを持っているか
@permission_required('polls.add_poll', raise_exception=True)
def add_poll(request):
    ...

# カスタム条件
@user_passes_test(lambda u: u.is_authenticated and u.email_verified)
def verified_only(request):
    ...

# クラスベースビューなら LoginRequiredMixin
from django.contrib.auth.mixins import LoginRequiredMixin

class MyPageView(LoginRequiredMixin, TemplateView):
    template_name = 'mypage.html'
    login_url = '/login/'

テンプレート内で次の URL を保持

ログイン後に元のページに戻すには:

ログイン

{# ログインフォーム側 #}
{% csrf_token %} {{ form.as_p }}

非匿名ユーザーの判定(旧 API)

記述意味備考
user.is_authenticatedログイン済か1.10+ から property(() 不要)
user.is_anonymous未ログインか同上
user.is_activeアカウント有効か停止アカウントは False
user.is_staff管理画面アクセス可admin/ で必要
user.is_superuser全権限perms 判定をバイパス

FAQ

Q: テンプレートで user が常に AnonymousUser になる
A: context processor の django.contrib.auth.context_processors.auth が抜けている可能性。settings.py を確認。または render() の代わりに自前の RequestContext を使い回している。

Q: DRF のテンプレートビューでログイン判定したい
A: APIView では request.user.is_authenticated を view 内で判定し、permission_classes = [IsAuthenticated] を設定。

Q: テンプレートで OR / AND を書きたい
A: {% if user.is_staff or user.is_superuser %} のように普通に or / and / not が使えます。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 環境構築とプロジェクト/アプリの作成
  2. MVC(MVT)のそれぞれの使い方と説明
  3. データベースへの接続と操作
  4. Django Administration
  5. git管理
  6. エラー一覧
  7. バージョンの確認方法
  8. ログ出力方法
  9. SQLのログ出力方法
  10. ログのローテート設定
  11. settings.pyの定数にアクセスする方法
  12. 本番環境へのインストールとアプリのデプロイ(apache編)
  13. 本番環境へのインストールとアプリのデプロイ(nginx編)
  14. djangoアプリの本番の開始URLを変更する
  15. 静的(static)ファイルの置き場所と読み込み(画像、css、js )
  16. CSRFトークンをAjaxで使用する方法
  17. ajaxの使用例(POST編)
  18. ファイルのアップロードとファイルの名前
  19. クイックスタート/チュートリアル
  20. ログイン機能
  21. テンプレート側のログイン判定
  22. ビュー側のログイン判定
  23. 管理者ユーザーの作成/判定と管理画面
  24. モデルのjson化とレスポンス
  25. runserverでポートを指定する方法
  26. cronによるバッチ実行
  27. テンプレートで利用する共通のcontextを定義する方法
  28. プログラムが本番サーバーで反映されない場合の対処法
  29. APIの作成
  30. cron用コマンド・ファイルの作成