Using Permissions In Views¶
Now that we’ve got our permissions defined, we need to write views that actually use them. If you’ve already used Django’s built-in permission mechanism, Bridgekeeper integrates with that:
from django.http import Http404
from django.shortcuts import get_object_or_404
from django.template.response import TemplateResponse
from . import models
def shrubbery_edit(request, shrubbery_id):
shrubbery = get_object_or_404(models.Shrubbery, id=shrubbery_id)
if not request.user.has_perm('shrubberies.change_shrubbery', shrubbery):
raise Http404()
return TemplateResponse(request, 'shrubbery_edit.html', {
'shrubbery': shrubbery,
})
We can also check permissions directly through Bridgekeeper. Remember, bridgekeeper.perms
is more or less just a dict, so we can pull it out of there and call the rule’s check()
method:
from bridgekeeper import perms
def shrubbery_edit(request, shrubbery_id):
# ...
if not perms['shrubberies.change_shrubbery'].check(request.user, shrubbery):
raise Http404()
# ...
Note
If you use Django’s has_perm()
, like in our first example, Django will consult all of your authentication backends to check permissions. For instance, if you’ve assigned permissions to users in your database through Django’s built-in user_permissions
, they’ll be checked as well. Similarly, if you have a third-party authentication backend (e.g. for social media, LDAP or Active Directory integration) that provides some form of permission checking, that will be checked too.
If you use Bridgekeeper directly, like in our second example, only Bridgekeeper permissions will be checked; in most cases this is what you want.
Filtering QuerySets¶
If we’re displaying a list, we can also filter a QuerySet so that it only contains objects that the currently-logged-in user holds a certain permission on.
from bridgekeeper import perms
from django.core.paginator import Paginator
from django.template.response import TemplateResponse
from . import models
def shrubbery_list(request, shrubbery_id):
all_shrubberies = models.Shrubbery.objects.all()
shrubberies = perms['shrubberies.view_shrubbery'].filter(request.user, all_shrubberies)
# 'shrubberies' is just a regular queryset, so we can do anything
# we would do with a normal queryset; in this case, let's paginate it
paginator = Paginator(shrubberies, 10)
page = paginator.page(1)
return TemplateResponse(request, 'shrubbery_list.html', {
'paginator': paginator,
'page': page,
'shrubberies': page.object_list,
})
Class-Based Views¶
All of the examples we’ve used so far have been function-based views. Of course, everything that we’ve covered so far will work inside a class-based view, but Bridgekeeper also comes with a handy shortcut in the form of QuerySetPermissionMixin
.
from bridgekeeper.mixins import QuerySetPermissionMixin
from django.views.generic import ListView, UpdateView
from . import models
class ShrubberyListView(QuerySetPermissionMixin, ListView):
model = models.Shrubbery
permission_name = 'shrubberies.view_shrubbery'
class ShrubberyUpdateView(QuerySetPermissionMixin, UpdateView):
model = models.Shrubbery
permission_name = 'shrubberies.change_shrubbery'
That’s all there is to it; these two views will now only show shrubberies that the currently-logged-in user has permission to view.
What next?¶
That’s the end of the tutorial; you should now be able to get started modelling your permissions with Bridgekeeper now!
You can read about the other ways you can check permissions, including more convenience shortcuts you can enable and ways to check things like whether somebody could, hypothetically, have a permission in the Checking Permissions guide. Or, find out more detail about writing rules and permissions in the Writing Rules and Permissions guide.
If there’s something that you don’t understand after following through this tutorial, or that you think could be explained better, please file a documentation bug so that we can improve the docs for future users.