Check permissions using the decorator¶
Note
A decorator is not the ultimate painkiller, if you need to deal with complex permission handling, take a look at Check permissions in python code.
The decorator syntax¶
Lets start with an example permission:
class FlatpagePermission(permissions.BasePermission):
label = 'flatpage_permission'
checks = ('can_do_foo',)
def can_do_foo(self):
# ...
authority.register(Campaign, FlatpagePermission)
A decorator for such a simple view would look like:
from authority.decorators import permission_required
@permission_required('flatpage_permission.can_do_foo')
def my_view(request):
# ...
The decorator automatically takes the user object from the view’s arguments
and calls can_do_foo
. If this function returns True
, the view gets
called, otherwise the user will be redirected to the login page.
Passing arguments to the permission¶
You can pass any arguments to the permission function. Assumed our permission function looks like this:
def can_do_foo(self, view_arg1, view_arg2=None):
# ...
Our decorator can grab the arguments from the view and passes it to the permission function. Just take the arguments from the view and place them as a string on the decorator:
@permission_required('flatpage_permission.can_do_foo', 'arg1', 'arg2')
def my_view(required, arg1, arg2):
# ...
What happens under the hood?:
# Assumed the view gets called like this
my_view(request, 'bla', 'blubb')
# At the end, the decorator would been called like this
can_do_foo('bla', 'blubb')
Passing queryset lookups to the permission¶
You can pass queryset lookups instead of an argument. This might look a bit strange first, but it can save you a ton of code. Instead of passing a simple string to the permission function, declare a tuple of the syntax:
(<model>, '<field_lookup>', 'view_arg')
# .. or ..
('<appname>.<modelname>', '<field_lookup>', 'view_arg')
Here is an example:
# permission.py
def can_do_foo(self, flatpage_instance=None):
# ...
# views.py
from django.contrib.flatpages.models import Flatpage
@permission_required('flatpage_permission.can_do_foo', (Flatpage, 'url__iexact', 'url'))
def flatpage(required, url):
# ...
What happens under the hood? It’s nearly the same as the simple decorator
would do, except that the argument is fetched with a get_object_or_404
statement. So this is the same:
(Flatpage, 'url__iexact', 'url')
get_object_or_404(Flatpage, 'url__iexact'='/about/')
Note
For all available field lookups, please refer to the Django documentation: Field lookups
Contributed decorators¶
django-authority contributes two decorators, the syntax of both is the same as described above:
- permission_required
- permission_required_or_403
In a nutshell, permission_required_or_403
does the same as permission_required
except it returns a Http403 Response instead of redirecting to the login page.
Just like Django’s 500.html
and 404.html
you are able to override the
template used in the permission denied page. Simply create a 403.html
template in your template directory. It will get the path of the denied page
passed as the context variable request_path
.