如何在Django 2.0中使用通用类视图限制用户访问他人创建的对象
嘿,刚好我之前折腾过类似的需求,在Django 2.0里用通用类视图实现用户只能访问自己的创意和创意组其实挺简单的,核心就是通过过滤查询集和权限验证来做数据隔离,我给你一步步拆解并附上可直接复用的代码示例:
1. 先给模型加上用户关联
首先得让你的创意(Idea)和创意组(IdeaGroup)模型明确归属,通过外键关联到当前用户:
# models.py from django.db import models from django.contrib.auth.models import User class IdeaGroup(models.Model): name = models.CharField(max_length=100) user = models.ForeignKey(User, on_delete=models.CASCADE) # 可添加其他字段,比如描述、创建时间等 class Idea(models.Model): title = models.CharField(max_length=200) content = models.TextField() group = models.ForeignKey(IdeaGroup, on_delete=models.CASCADE) user = models.ForeignKey(User, on_delete=models.CASCADE) # 可添加其他字段,比如标签、创建时间等
2. 重写通用类视图的get_queryset方法
通用类视图默认会返回全量数据,我们需要重写get_queryset方法,只筛选当前登录用户的内容,以列表和详情视图为例:
创意组列表视图
# views.py from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from .models import IdeaGroup, Idea class IdeaGroupListView(LoginRequiredMixin, ListView): model = IdeaGroup template_name = 'your_app/ideagroup_list.html' # 替换成你的模板路径 context_object_name = 'groups' def get_queryset(self): # 只返回当前用户的创意组,按创建时间倒序排列 return IdeaGroup.objects.filter(user=self.request.user).order_by('-id')
创意详情视图
class IdeaDetailView(LoginRequiredMixin, DetailView): model = Idea def get_queryset(self): # 过滤出当前用户的创意,防止用户手动修改URL参数访问他人内容 return Idea.objects.filter(user=self.request.user)
3. 用UserPassesTestMixin确保修改/删除权限
对于更新、删除这类敏感操作,仅过滤查询集还不够,我们可以用UserPassesTestMixin在访问视图前验证用户是否是内容所有者:
创意更新视图
class IdeaUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView): model = Idea fields = ['title', 'content', 'group'] # 允许用户修改的字段 template_name = 'your_app/idea_form.html' def form_valid(self, form): # 确保更新时内容归属不会被篡改 form.instance.user = self.request.user return super().form_valid(form) def test_func(self): # 验证当前用户是该创意的所有者 idea = self.get_object() return self.request.user == idea.user
创意删除视图
class IdeaDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView): model = Idea success_url = '/ideas/' # 删除后跳转的URL,可根据你的路由调整 def test_func(self): idea = self.get_object() return self.request.user == idea.user
4. 自动关联用户到新创建的内容
在创建视图里,我们可以自动把当前登录用户赋值给新内容,不需要用户手动选择:
class IdeaGroupCreateView(LoginRequiredMixin, CreateView): model = IdeaGroup fields = ['name'] template_name = 'your_app/ideagroup_form.html' def form_valid(self, form): form.instance.user = self.request.user return super().form_valid(form) class IdeaCreateView(LoginRequiredMixin, CreateView): model = Idea fields = ['title', 'content', 'group'] template_name = 'your_app/idea_form.html' def form_valid(self, form): form.instance.user = self.request.user return super().form_valid(form)
示例URL配置
最后把这些视图映射到URL,在urls.py中添加如下配置:
# urls.py from django.urls import path from .views import ( IdeaGroupListView, IdeaGroupCreateView, IdeaDetailView, IdeaCreateView, IdeaUpdateView, IdeaDeleteView ) urlpatterns = [ # 创意组相关路由 path('groups/', IdeaGroupListView.as_view(), name='group-list'), path('groups/new/', IdeaGroupCreateView.as_view(), name='group-create'), # 创意相关路由 path('ideas/<int:pk>/', IdeaDetailView.as_view(), name='idea-detail'), path('ideas/new/', IdeaCreateView.as_view(), name='idea-create'), path('ideas/<int:pk>/update/', IdeaUpdateView.as_view(), name='idea-update'), path('ideas/<int:pk>/delete/', IdeaDeleteView.as_view(), name='idea-delete'), ]
额外小提示
- 所有需要登录才能访问的视图都要加上
LoginRequiredMixin,未登录用户会自动被重定向到登录页面(Django默认配置)。 - 如果你的模板里有展示内容列表的逻辑,也要确保只渲染当前用户的内容,避免前端泄露数据。
内容的提问来源于stack exchange,提问作者user4850501
相关产品推荐
相关产品推荐

