Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

やりたいこと

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

chanyou0311
大手企業向けにSNSのマーケティング支援を行っている事業部で、データ分析基盤やWebアプリケーションを構築・運用していいます。
https://chanyou.hatenablog.jp
gaiax
人と人をつなげる Empowering the people to connect.
http://www.gaiax.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした