6
9

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 5 years have passed since last update.

DjangoのUserPassesTestMixinを使って柔軟にアクセス制御する

Last updated at Posted at 2019-07-29

やりたいこと

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が違ってうまくいかないので、もう少し処理を抽象化する必要がありそうです。

6
9
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
6
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?