Django基于类视图实现仅关联成员可访问帖子成员列表的权限控制
permission_required配置的实际作用 - 该配置来自Django内置的
PermissionRequiredMixin,是类视图中用于实现模型级权限校验的配置项 - 配置传入的权限字符串(比如示例里的
blogpost.view_all_blogpost_members)会作为校验规则:只有当前登录用户被分配了对应权限,才能正常访问视图 - 校验不通过时,默认会按照配置跳转登录页,或返回403无权限响应
- 这种校验是全局维度的权限判断,无法实现“用户仅能查看自己作为关联成员的单篇博文成员列表”这类和具体数据绑定的权限规则,这也是仅靠这个配置满足不了当前业务需求的原因。
之前所有尝试失效的核心原因
- 原代码在
get_context_data中直接调用object.members.all:get_context_data的作用是组装模板上下文,不存在可以直接引用的全局object变量,会直接触发未定义变量报错;且在该方法内手动调用render()会打破DetailView内置的渲染流程,导致视图逻辑混乱。 - 参考dispatch实现的逻辑存在硬伤:判断用户属于成员列表时反而触发跳转回当前视图的逻辑,既没有设置校验通过的放行分支,也没有实现非成员跳首页的规则,最终会因为返回值不合法抛出视图错误。
- 参考
UserPassesTestMixin实现的语法错误:post.members.objects.all属于对多对多关联字段的错误调用——关联字段本身没有objects属性(objects是模型的默认管理器),正确的关联字段查询应该是post.members.all,这行错误代码会直接触发属性不存在的报错。 - 权限校验的触发时机不对:把校验逻辑写在
get_context_data里,相当于已经走完了拉取数据、权限前置判断的全流程才做校验,完全违背类视图的执行流程设计。
符合业务规则的正确实现
结合Django类视图的最佳实践,使用UserPassesTestMixin实现自定义数据级权限校验是最规范的方案,注意Mixin的加载顺序(越靠前的Mixin越先执行校验逻辑),完整代码如下:
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin class MemberListView(LoginRequiredMixin, UserPassesTestMixin, BlogPostMixin, DetailView): login_url = 'must_authenticate' template_name = "HomeFeed/membersof_yourpost.html" # 权限校验不通过时,不抛出403错误,直接跳转到站点首页 raise_exception = False login_url = 'home' # test_func是UserPassesTestMixin要求实现的校验方法,返回True则放行访问 def test_func(self): # 获取当前请求对应的目标博文对象 target_post = self.get_object() # 数据库层面校验当前用户是否在博文的关联成员列表中,避免全量拉取成员列表到内存 return target_post.members.filter(pk=self.request.user.pk).exists()
代码实现的逻辑完全匹配业务规则:
- 先通过
LoginRequiredMixin校验用户登录状态:未登录用户跳转到指定的登录页 - 已登录用户进入
UserPassesTestMixin的校验流程:如果当前用户不属于目标博文的成员列表,直接跳转到站点首页 - 校验通过后由DetailView自动拉取博文对象、渲染对应模板,模板原有的成员列表遍历代码不需要做任何修改即可正常运行。
注意点:
- 不要删除DetailView的默认渲染流程、不要在
get_context_data里手动返回render()响应 - 多对多关联字段的查询不要多加多余的
.objects调用 - Mixin的顺序不能随意调整,必须把登录校验、权限校验的Mixin放在业务视图父类之前,保证校验逻辑先执行
内容的提问来源于stack exchange,提问作者kknam
相关产品推荐
相关产品推荐

