django-authority/docs/check_decorator.txt
2011-02-21 09:09:32 -08:00

115 lines
3.7 KiB
Text

.. _check-decorator:
=====================================
Check permissions using the decorator
=====================================
.. index::
single: permission_required
single: permission_required_or_403
.. note:: A decorator is not the ultimate painkiller, if you need to deal with
complex permission handling, take a look at :ref:`check-python`.
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`_
.. _Field lookups: http://docs.djangoproject.com/en/dev/ref/models/querysets/#id7
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``.