DjangoにはPermission
というモデルがあり、Djangoのmodelを作成すると自動で生成されます。それによって管理画面では対応する権限を持つユーザーのみがテーブルデータを作成・更新・削除できるといった制限が可能です。今回はこのPermission
を使ってViewの制限をしたいと思います。
独自のPermission
を作る
既存のPermission
データを使わずに新しく作ってみます。
ContentType
の指定
Permission
モデルは外部キーとしてContentType
を指定する必要があるので、対応するContentType
が無くてはなりません。制限しようとしているViewのあるアプリケーションのContentType
を指定すればいいと思いますが、独自のものを作ってもいいかもしれません。
from django.contrib.contenttypes.models import ContentType
ContentType.objects.create(
app_label='app_label', name='name', model='model')
app_label
として指定しているのはアプリケーション名。つまりsettingsのINSTALLED_APPS
などに指定するモジュール名の末尾です。
Permission
データの作成
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
content_type = ContentType.objects.get(
app_label='app_label', name='name', model='model')
Permission.objects.create(
content_type_id=content_type.id, name='name', codename='codename')
name
は'Can add permission'
などパーミッションの表示名で、codename
は'add_permission'
など、識別名です。
ユーザーにPermission
を付与
Djangoの管理画面のユーザー編集画面から権限の付与ができます。
ユーザーが特定のPermission
を持っているか調べる
User
インスタンスのhas_perm
を呼べば特定のPermission
を持っているか確認できます。引数に渡すのは'app_label.codename'
という形になります。たとえばユーザー追加のパーミッションは'auth.add_user'
です。
from django.contrib.auth import get_user_model
User = get_user_model()
user = User.objects.get(pk=1)
user.has_perm('{app_label}.{codename}'.format(
app_label='app_label', codename='codename'))
デコレーターでViewを制限
(追記あり)
参考として、Djangoではスタッフユーザーだけが見る事ができるViewを作る場合、デコレータを利用する方法があります。
from django.contrib.admin.views.decorators import staff_member_required
from django.utils.decorators import method_decorator
from django.views.generic.base import View
class SpamView(View):
@method_decorator(staff_member_required)
def dispatch(self, *args, **kwargs):
return super(SpamView, self).dispatch(*args, **kwargs)
これをまねて特定のパーミッションを持つユーザーだけが見る事ができるViewを作ります。
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.decorators import user_passes_test
def get_permission_deco(permission_codename,
redirect_field_name=REDIRECT_FIELD_NAME,
login_url='admin:login'):
def deco(view_func):
return user_passes_test(
lambda u: u.has_perm(permission_codename),
login_url=login_url,
redirect_field_name=redirect_field_name
)(view_func)
return deco
from django.utils.decorators import method_decorator
from django.views.generic.base import View
from .decorators import get_permission_deco
class EggView(View):
@method_decorator(get_permission_deco('app_label.codename'))
def dispatch(self, *args, **kwargs):
return super(EggView, self).dispatch(*args, **kwargs)
(追記)
小細工しなくてもDjangoにはpermission_required
というのがありました。
https://docs.djangoproject.com/ja/1.10/topics/auth/default/#the-permission-required-decorator
カスタムタグでテンプレートを制限
カスタムタグの作り方の詳細はこの記事の範囲を超えますので省略しますが、カスタムタグを使ってテンプレートを制限する事もあるかと思うので一例を載せておきます。
from django import template
register = template.Library()
@register.filter(name='has_perm')
def has_perm(user, permission_name):
return user.has_perm(permission_name)
{% load perm_extra %}
{% if user|has_perm:'app_label.codename' %}
<a href="/path">編集ページへ</a>
{% else %}
<del>編集ページへ</del>(権限がありません)
{% endif %}