Права пользователя в Django
Настройка прав пользователей является одной из основных частей при разработке проектов и может быстро стать достаточно сложной. Разберем основные приемы на примере блога.
Представления
Обычно поверку прав пользователя производят в представлениях (views.py). Возьмем пример обновления записи в блоге BlogUpdateView:
# blog/views.py
class BlogUpdateView(UpdateView):
model = Post
template_name = 'post_edit.html'
fields = ['title', 'body']
LoginRequired
Мы решили разрешить обновление записей только авторизированным пользователям. Решений для этого существует несколько, но самым простым будет использование готового миксина LoginRequiredMixin.
Если вам еще не приходилось использовать миксины, то запомните, что они выполняются в очередности слева направо, поэтому добавить этот миксин нужно перед UpdateView. Таким образом неавторизованный пользователь увидит сообщение об ошибке.
# 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
Следующий уровень проверки ‒ что-то уникальное для пользователя. Например, разрешим обновлять только записи самого пользователя. Для этого можно использовать 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
Здесь сначала происходит проверка авторизации, а уже после нее (если она прошла успешно) проверяем права доступа к конкретному объекту.
В методе test_func() расположена вся логика проверки прав, данным методы будет вызван из миксина UserPassesTestMixin
, поэтому его необходимо переопределить. Если автор выбранного объекта равен текущему авторизованному пользователю, то проверка проходит успешно, иначе будет сгенерированна ошибка доступа.
Данную проверку можно было сделать, например, в методе dispatch(), но использование UserPassesTestMixin
выглядит более элегантно, т.к. был разработан специально для таких случаев.