.. _create-per-object-permission: ============================== Create a per-object permission ============================== django-authority provides a super simple but nifty feature called *per-object permission*. A description would be:: Attach a to an object Attach a to an user If the user has and the object has then do-something, otherwise do-something-else. This might sound strange but let's have a closer look on this pattern. In terms of users and flatpages a visual example would be: .. image:: .static/authority-object-1to1.png *The user is allowed to review the flatpage "Events".* You are not limited to a 1:1 relation, you can add this ``codename`` to multiple objects: .. image:: .static/authority-object-1toN.png *The user is allowed to review the flatpages "Events" and "Contact".* And you can do this with any objects in any direction: .. image:: .static/authority-object-NtoN.png *The user is allowed to review the flatpages "Events" and "Contact". Another user is allowed to publish the flatpage "Events".* Create per-object permissions ============================= Creating per-object permissions is super simple. See this piece of permission class code:: class FlatPagePermission(BasePermission): label = 'flatpage_permission' checks = ('review',) authority.register(FlatPage, FlatPagePermission) This permission class is similar to the one we already created in :ref:`create-basic-permission` but we added the line:: checks = ('review',) This tells the permission class that it has a permission check (or ``codename``) ``review``. Under the hood this check gets translated to ``review_flatpage`` (``review_``). .. important:: Be sure that you have understand that we have not written any line of code yet. We just added the ``codename`` to the checks attribute. Attach per-object permissions to objects ======================================== Please see :ref:`handling-admin` for this. Check per-object permissions ============================ As we noted above, we have not written any permission comparing code yet. This is your work. In theory the permission lookup for per-object permissions is:: if has and has : return True else: return False .. important:: The syntax is similiar to the permission checks we've already seen in :ref:`create-basic-permission` for the basic permissions but now we have to pass each function a model instance we want to check! In your python code ------------------- :: from myapp.permissions import FlatPagePermission def my_view(request): check = FlatPagePermission(request.user) flatpage_object = Flatpage.objects.get(url='/homepage/') if check.review_flatpage(flatpage_object): print "Yay, you can change *this* flatpage!" Using the view decorator ------------------------ :: from django.contrib.auth import Flatpage from authority.decorators import permission_required_or_403 @permission_required_or_403('flatpage_permission.review_flatpage', (Flatpage, 'url__iexact', 'url')) # The flatpage_object def my_view(request, url): # ... See :ref:`check-decorator` how the decorator works in detail. In your templates ----------------- :: {% ifhasperm "flatpage_permission.review_flatpage" request.user flatpage_object %} Yay, you can change *this* flatpage! {% else %} Nope, sorry. You aren't allowed to change *this* flatpage. {% endifhasperm %} See :ref:`check-templates` how the template tag works in detail.