Django has a model called Permission
, which is automatically generated when you create a Django model. As a result, on the management screen, only users with the corresponding authority can create, update, and delete table data. This time I would like to use this Permission
to limit the view.
Permission
Let's create a new one without using the existing Permission
data.
ContentType
The Permission
model requires you to specify ContentType
as a foreign key, so there must be a corresponding ContentType
. I think you can specify the ContentType
of the application that has the View you are trying to limit, but you may want to create your own.
from django.contrib.contenttypes.models import ContentType
ContentType.objects.create(
app_label='app_label', name='name', model='model')
The application name is specified as ʻapp_label. In other words, it is the end of the module name specified in settings such as ʻINSTALLED_APPS
.
Permission
datafrom 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
is the display name of the permission, such as'Can add permission'
, and codename
is the distinguished name, such as'add_permission'
.
Permission
to userYou can grant permissions from the user edit screen on the Django admin screen.
Permission
You can check if you have a specific Permission
by calling has_perm
of the ʻUserinstance. Pass it as an argument in the form
'app_label.codename'. For example, the permission to add a user is
'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'))
(Additional notes)
As a reference, Django has a way to use a decorator to create a View that only staff users can see.
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)
By imitating this, we will create a View that can only be viewed by users with specific permissions.
decorators.py
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
view.py
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)
There was a permission_required
in Django without any tricks.
https://docs.djangoproject.com/ja/1.10/topics/auth/default/#the-permission-required-decorator
The details of how to create a custom tag are beyond the scope of this article, so I will omit it, but I think that you may limit the template by using a custom tag, so I will give an example.
perm_extra.py
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">Go to edit page</a>
{% else %}
<del>Go to edit page</del>(No authority)
{% endif %}