You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 17:07:35