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.

Back to Top