User permissions in Django
Configuring user rights is one of the main parts when developing projects and can quickly become quite complex. Let's break down the main techniques on the example of a blog.
Views
User rights are usually checked in views (views.py). Let's take the example of updating a blog post BlogUpdateView:
# blog/views.py
class BlogUpdateView(UpdateView):
model = Post
template_name = 'post_edit.html'
fields = ['title', 'body']
LoginRequired
We have decided to allow only authorized users to update records. There are several solutions for this, but the easiest one is to use the ready-made LoginRequiredMixin.
If you haven't had to use myxins yet, remember that they are executed in order from left to right, so you need to add this myxin before UpdateView. This way an unauthorized user will see an error message.
# blog/views.py
from django.contrib.auth.mixins import LoginRequiredMixin
class BlogUpdateView(LoginRequiredMixin, UpdateView):
model = Post
template_name = 'post_edit.html'
fields = ['title', 'body']
UserPassesTextMixin
The next level of validation is something unique to the user. For example, let's allow only the user's own records to be updated. For this purpose we can use UserPassesTextMixin.
# blog/views.py
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
class BlogUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Post
template_name = 'post_edit.html'
fields = ['title', 'body']
def test_func(self):
obj = self.get_object()
return obj.author == self.request.user
Here we first check authorization, and after it (if it was successful) we check access rights to a particular object.
The test_func() method contains all the logic for checking permissions, this method will be called from the UserPassesTestMixin
mixin, so it must be overridden. If the author of the selected object is equal to the current authorized user, the test is successful, otherwise an access error will be generated.
This check could be done, for example, in the dispatch() method, but using UserPassesTestMixin
looks more elegant, since it was designed specifically for such cases.