Django中通过SiteDispatchView根据用户角色跳转至ListView或DetailView并传递上下文时遇AttributeError问题
解决AttributeError并实现角色跳转及用户站点传递
首先咱们拆解下你遇到的问题:AttributeError的核心原因是直接调用SiteDetailView.as_view()时,没有按照DetailView的规则传递pk(或slug)参数——你的URL配置明确要求<int:pk>,但你直接传入了site对象,这和它的参数预期不匹配。
下面给你两种可行的解决方案,按需选择:
方案一:在Dispatch时传递pk参数
修改SiteDispatchView的dispatch方法,把用户站点的pk作为参数传给DetailView,匹配URL配置的要求:
class SiteDispatchView(LoginRequiredMixin, View): def dispatch(self, request, *args, **kwargs): if request.user.role >= 2: # 传递site的pk给DetailView,符合URL里<int:pk>的要求 return SiteDetailView.as_view()(request, pk=request.user.site.pk) else: return SiteListView.as_view()(request)
同时别忘了修复SiteDetailView里的get_success_url——原来的写法没有传递pk参数,会导致跳转时URL不完整:
class SiteDetailView(LoginRequiredMixin, generic.DetailView): template_name = "project_site/site_detail.html" context_object_name = "project_sites" model = Site def get_success_url(self): # 补充pk参数,生成正确的详情页URL return reverse("project_site:detail-site", kwargs={"pk": self.object.pk})
方案二:重写DetailView的get_object方法(无需URL pk)
如果你的业务逻辑是用户只能访问自己关联的站点,可以重写get_object方法,让DetailView直接获取当前用户的site,不需要从URL取pk:
class SiteDetailView(LoginRequiredMixin, generic.DetailView): template_name = "project_site/site_detail.html" context_object_name = "project_sites" model = Site def get_object(self, queryset=None): # 直接返回当前用户绑定的site对象 return self.request.user.site def get_success_url(self): return reverse("project_site:detail-site", kwargs={"pk": self.object.pk})
对应的SiteDispatchView可以简化成:
class SiteDispatchView(LoginRequiredMixin, View): def dispatch(self, request, *args, **kwargs): if request.user.role >= 2: # 不需要传pk了,DetailView会自己通过get_object获取站点 return SiteDetailView.as_view()(request) else: return SiteListView.as_view()(request)
这种方案下,你可以考虑把URL改成不需要pk的形式(比如path('detail/', SiteDetailView.as_view(), name='detail-site')),更贴合“用户只能看自己站点”的逻辑,避免用户手动修改URL pk访问其他站点。
额外建议
如果用方案一,最好在SiteDetailView里加权限校验,确保用户只能访问自己的站点:
def get_queryset(self): # 只返回当前用户关联的站点数据 return Site.objects.filter(pk=self.request.user.site.pk)
这样能避免恶意用户通过修改URL里的pk访问不属于自己的站点。
内容的提问来源于stack exchange,提问作者Bernard Diamante
相关产品推荐
相关产品推荐

