結論
- ユーザのアクセス制限を行うLoginRequiredMixin, UserPassesTestMixinクラスを紹介。
- 両クラス共通で、AccessMixinクラスを継承している。
- 基本的に両クラス、制限をかけたいビュークラスに継承するだけでそのビューに対してアクセス制限をかけることができる。
- 継承する際は、LoginRequiredMixinが一番左、UserPassesTestMixinがその次に指定する必要がある。そうでない場合は、エラー。
- これらのクラスを使用するには、ログイン・ログアウト機能を作成しておく必要がある
- LoginRequiredMixinでできることは、UserPassesTestMixinでもできる。強化版の印象。
アクセス制限クラス | 用途 |
---|---|
LoginRequiredMixin | ログインしていないユーザからのアクセスに制限をかけたい場合に使用する |
UserPassesTestMixin | ログイン制限をかけた上で、独自のアクセス制限を追加で設定したい場合に使用する |
LoginRequiredMixin
環境変数を設定するだけで使用可能
- 定義の順序:
- settinga.pyで、リダイレクトに関する
LOGIN_URL, LOGIN_REDIRECT_URL, LOGOUT_REDIRECT_URL
3つの環境変数を設定する - クラスをimport
- アクセス制限をかけたい対象のビュークラスに継承させる
- settinga.pyで、リダイレクトに関する
親の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パラメータがある前提
※ログイン機能を実装しておく必要がある