やりたいこと
Djangoでログインしたユーザーの情報を、自分自身のみが編集できるようにしたい。
Django組み込みのPermissionモデルを活用しようとしても、ログインしたユーザー自身に動的に制限をかけるのは相当難しそう。
そこで活用できるのが UserPassesTestMixin です。
UserPassesTestMixinとは?
Django 1.9でリリースされた Permission mixins for class-based views に内包されている機能のこと。
公式ドキュメントでも丁寧に解説されています。
Djangoの認証システムを使用する | Django ドキュメント | Django
UserPassesTestMixinを使ってみる
百聞は一見にしかずということで例として、UserPassesTestMixinを使って gmail.comドメインのユーザーのみがアクセスできるビュー を定義してみます。
UserPassesTestMixinの拡張
まずは下記のようにカスタムミックスインを定義します。
# mixins.py
from django.contrib.auth.mixins import UserPassesTestMixin
class OnlyGmailUserMixin(UserPassesTestMixin):
raise_exception = True
def test_func(self):
return self.request.user.email.endswith('@gmail.com')
test_func
というメソッドをオーバーライドして、そのメソッド内で条件分岐式を記述しておきます。
test_func
の返り値で制限をかけるかかけないかが決まります。
ビューの定義
そして、先ほど作成したカスタムミックスインを継承したクラスビューを定義します
# views.py
from django.contrib.auth.models import User
from django.views.generic import TemplateView
from .mixins import OnlyGmailUserMixin
class OnlyGmailUserView(OnlyGmailUserMixin, TemplateView):
model = User
template_name = "home.html"
以上です。めちゃ簡単!!!
自分自身のみが編集できるビューを定義する
当初の「Djangoでログインしたユーザーの情報を、自分自身のみが編集できるようにする」は UserPassesTestMixin を使うことで簡単に実装ができます。
# mixins.py
from django.contrib.auth.mixins import UserPassesTestMixin
class OnlyYouMixin(UserPassesTestMixin):
raise_exception = True
def test_func(self):
user = self.request.user
return user.pk == self.kwargs['pk']
# views.py
from django.contrib.auth.models import User
from django.views.generic import UpdateView
from .forms import UserForm # 別途フォームを定義しておく
from .mixins import OnlyYouMixin
class UserUpdateView(OnlyYouMixin, UpdateView):
model = User
template_name = "users/update.html"
form_class = UserForm
def get_success_url(self):
return resolve_url('users:update', pk=self.kwargs['pk'])
まとめ
最近になって初めてUserPassesTestMixinを使ってみましたが、簡単で応用の効くMixinで面白いですね。
ただ、複数のUserPassesTestMixinを継承できないようなので、その点は注意が必要です。
また、最後のOnlyYouMixinですが、これをUserモデル以外のモデルで使おうとするとPKが違ってうまくいかないので、もう少し処理を抽象化する必要がありそうです。