如何在Django UpdateView中仅允许文章作者访问文章更新页面
嘿,要实现只有文章作者能访问更新页面的需求,Django给了咱们两种很实用的方案,我给你拆解一下:
方案一:使用UserPassesTestMixin(推荐)
Django自带的UserPassesTestMixin专门用来做这种基于用户的权限校验,咱们只需要把它加到你的类视图继承列表里,再重写test_func方法就行。注意Mixin的顺序要对——先继承LoginRequiredMixin(保证用户已登录),再继承UserPassesTestMixin(做权限校验),最后才是UpdateView,因为Django会从左到右执行Mixin的逻辑。
修改后的完整代码如下:
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from django.views.generic.edit import UpdateView from .models import Article, StocksETFsBonds, Tag from django.db.models import Count class ArticleUpdate(LoginRequiredMixin, UserPassesTestMixin, UpdateView): model = Article template_name = 'articles/update_view.html' context_object_name = 'article_update' form_class = ArticleForm def test_func(self): # 获取当前要编辑的文章对象 article = self.get_object() # 校验:当前登录用户是否等于文章的作者 return self.request.user == article.author def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['securities_types_list'] = StocksETFsBonds.objects.all() context['tags_list'] = Tag.objects.annotate(articles_quantiy=Count('taggit_taggeditem_items')).order_by('-articles_quantiy')[:10] return context
如果权限校验不通过,Django会默认返回403 Forbidden页面。如果你想自定义这个页面的内容,可以重写handle_no_permission方法。
方案二:重写get_object方法
另一种方式是直接在获取文章对象的时候做权限校验,这种方式更直接,适合不想多继承一个Mixin的场景。我们只需要重写get_object方法,在拿到文章后判断用户是否是作者,不是的话抛出PermissionDenied异常。
代码示例:
from django.contrib.auth.mixins import LoginRequiredMixin from django.views.generic.edit import UpdateView from django.core.exceptions import PermissionDenied from .models import Article, StocksETFsBonds, Tag from django.db.models import Count class ArticleUpdate(LoginRequiredMixin, UpdateView): model = Article template_name = 'articles/update_view.html' context_object_name = 'article_update' form_class = ArticleForm def get_object(self, queryset=None): # 先调用父类方法获取文章对象 article = super().get_object(queryset=queryset) # 校验权限:如果当前用户不是作者,抛出权限异常 if article.author != self.request.user: raise PermissionDenied("你没有权限修改这篇文章") return article def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['securities_types_list'] = StocksETFsBonds.objects.all() context['tags_list'] = Tag.objects.annotate(articles_quantiy=Count('taggit_taggeditem_items')).order_by('-articles_quantiy')[:10] return context
这种方法的好处是在获取对象的第一环节就拦截了无权限的请求,避免后续不必要的处理,而且可以自定义异常提示语。
注意事项
要确保你的Article模型里有一个author字段,关联到Django的User模型,比如:
from django.db import models from django.contrib.auth.models import User class Article(models.Model): author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='articles') title = models.CharField(max_length=200) content = models.TextField() # 其他字段...
内容的提问来源于stack exchange,提问作者ilsurealism
相关产品推荐
相关产品推荐

