4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Djangoでアクセス制限を行う(AccessMixinクラス)

Last updated at Posted at 2022-09-09

結論

  • ユーザのアクセス制限を行うLoginRequiredMixin, UserPassesTestMixinクラスを紹介。
  • 両クラス共通で、AccessMixinクラスを継承している。
  • 基本的に両クラス、制限をかけたいビュークラスに継承するだけでそのビューに対してアクセス制限をかけることができる。
  • 継承する際は、LoginRequiredMixinが一番左、UserPassesTestMixinがその次に指定する必要がある。そうでない場合は、エラー。
  • これらのクラスを使用するには、ログイン・ログアウト機能を作成しておく必要がある
  • LoginRequiredMixinでできることは、UserPassesTestMixinでもできる。強化版の印象。
アクセス制限クラス 用途
LoginRequiredMixin ログインしていないユーザからのアクセスに制限をかけたい場合に使用する
UserPassesTestMixin ログイン制限をかけた上で、独自のアクセス制限を追加で設定したい場合に使用する

LoginRequiredMixin

環境変数を設定するだけで使用可能

  • 定義の順序:
    • settinga.pyで、リダイレクトに関するLOGIN_URL, LOGIN_REDIRECT_URL, LOGOUT_REDIRECT_URL3つの環境変数を設定する
    • クラスをimport
    • アクセス制限をかけたい対象のビュークラスに継承させる
親のAccessMixinクラスの属性とメソッド 説明
raise_exception ログインしていないユーザがアクセスした場合、403ページにリダイレクトさせるのかを指定する。Falseがデフォルト。
handle_no_permission() raise_exceptionの値でリダイレクト先を決めるメソッド。raise_exception = False(デフォルト)の場合、リダイレクト先を指定する(デフォルトでsettings.LOGIN_URLにリダイレクト)。Trueの場合、403ページにリダイレクトさせる。
  • ただし、ログイン済みのユーザであれば、reise_exceptionの値がFalseでも403エラーを返す。
    • ログイン済みの状態なので、ログインページにリダイレクトさせないため。

※継承する際は引数の最初に記述すること。でないとエラー。
※上記の3つの環境変数を設定し、ビュークラスに継承するだけで、ログイン制限をかけることができる。変数やメソッドをオーバーライドする必要はない。

具体例

views.py
from django.views.generic import ListView
from django.contrib.auth.mixins import LoginRequiredMixin

from .models import Post

class Index(LoginRequiredMixin, ListView):
    template_name = 'report/index.html'
    model = Post
    ordering = 'created' # 新規作成順 '-createdで降順'
  • LoginRequiredMixinを継承するだけで、対象のビューにログインのアクセス制限がかかる
    • つまり、ログイン済みのユーザからのリクエストがないとこのビューを実行しない

UserPassesTestMixin

  • 定義の順序:
    • クラスをimport
    • 共通化させるクラスを作成(以下の具体例では、OwnerOnlyクラス)
    • test_func()の定義(Trueでアクセス可、Falseでアクセス不可)
    • test_func()の戻り値がFalse用にリダイレクト先を指定(handle_no_permission())
親のAccessMixinクラスの属性とメソッド 説明
raise_exception ログインしていないユーザがアクセスした場合、403ページにリダイレクトさせるのかを指定する。Falseがデフォルト。
handle_no_permission() raise_exceptionの値でリダイレクト先を決めるメソッド。raise_exception = False(デフォルト)の場合、リダイレクト先を指定する(デフォルトでsettings.LOGIN_URLにリダイレクト)。Trueの場合、403ページにリダイレクトさせる。
test_func() ログインに成功したユーザに対して、独自のアクセス制限を設定する。戻り値がTrueの場合、サイトへのアクセスを許可する。Falseの場合、アクセスを拒否し、403ページへリダイレクトさせる。
  • ただし、ログイン済みのユーザであれば、reise_exceptionの値がFalseでも403エラーを返す。
    • ログイン済みの状態なので、ログインページにリダイレクトさせないため。

※LoginRequiredMixinと同様、継承する際は引数の最初に記述すること。でないとエラー。

具体例

①独自制限を共通化させたい場合

views.py
from django.contrib.auth.mixins import UserPassesTestMixin
from django.shortcuts import redirect

class OwnerOnly(UserPassesTestMixin):
    def test_func(self):
        object = self.get_object()
        return object.user == self.request.user
    
    def handle_no_permission(self):
        return redirect("Detail", pk=self.kwargs["pk"])
  • 他のビュークラスでも独自の設定を共通化させるために、UserPassesTestMixinクラスを継承したOwnerOnlyというクラスを定義している。
  • test_func関数では、継承させる予定のUpdateViewで取得した1件のレコードのカラム(user)の値とログイン中のユーザーが一致している場合は、Trueを返す。
  • test_func関数の戻り値がFalseの場合、handle_no_permission関数を実行する。
  • handle_no_permission関数によって、詳細ページへリダイレクトする。

※UpdateViewに継承することを前提に定義している(UpdateViewで使用できる属性、メソッドも定義している)

②独自制限を1つのビューに設定したい場合

views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.mixins import UserPassesTestMixin
from django.views.generic import DetailView

class Detail(LoginRequiredMixin, UserPassesTestMixin, DetailView):
    template_name = 'report/detaile.html'
    model = Post

    def test_func(self):
        # 現在ログイン中ユーザのpkとURLのpkパラメータが同じ、またはsuperuserならTrue
        current_user = self.request.user
        return current_user.pk == self.kwargs['pk'] or current_user.is_superuser
  • 継承時は、LoginRequiredMixinが一番左
  • 現在ログイン中のユーザは、self.request.userで取得
  • self.kwargs['pk']によって、URLからpkパラメータの値を取得

※urls.pyで設定したURLに、pkパラメータがある前提
※ログイン機能を実装しておく必要がある

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?