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

Django返回HttpResponseNotFound报错:context must be a dict rather than type

Django权限控制问题:跨公司Item访问未返回404反而触发500错误

我正在开发一个Django项目,其中有一个名为Item的资源。需求是用户仅能查看同公司的Item详情,否则返回404。我编写了如下代码:

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)

    # To only show items in your company
    if (context['item'].company != getCompany(self.request.user)):
        return HttpResponseNotFound

    return context

getCompany是我自定义的函数,用于获取用户所属公司,该函数已在其他功能中验证可用。但访问其他公司的Item详情时,未返回预期的404,反而触发内部服务器错误,报错信息为:

Internal Server Error: /fr/items/5/
Traceback (most recent call last):
  File "/Users/username/Documents/Work/Inventory/inventory-env/lib/python3.9/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/Users/username/Documents/Work/Inventory/inventory-env/lib/python3.9/site-packages/django/core/handlers/base.py", line 220, in _get_response
    response = response.render()
  File "/Users/username/Documents/Work/Inventory/inventory-env/lib/python3.9/site-packages/django/template/response.py", line 114, in render
    self.content = self.rendered_content
  File "/Users/username/Documents/Work/Inventory/inventory-env/lib/python3.9/site-packages/django/template/response.py", line 92, in rendered_content
    return template.render(context, self._request)
  File "/Users/username/Documents/Work/Inventory/inventory-env/lib/python3.9/site-packages/django/template/backends/django.py", line 58, in render
    context = make_context(
  File "/Users/username/Documents/Work/Inventory/inventory-env/lib/python3.9/site-packages/django/template/context.py", line 278, in make_context
    raise TypeError(
TypeError: context must be a dict rather than type.

问题原因与解决方案

核心问题

get_context_data方法的职责是返回字典类型的模板上下文,但你直接返回了HttpResponseNotFound类(而非实例),后续模板渲染流程会把这个类当作上下文字典处理,最终触发TypeError。此外,在get_context_data中处理权限校验并返回响应,本身就不符合Django视图的设计逻辑。

正确实现方式

应该在视图获取对象的入口方法get_object中做权限校验,不符合条件则抛出Http404异常,Django会自动将其转换为404响应:

from django.http import Http404

def get_object(self, queryset=None):
    obj = super().get_object(queryset=queryset)
    # 校验用户所属公司与Item公司是否一致
    if obj.company != getCompany(self.request.user):
        raise Http404("你无权访问该资源")
    return obj

原有的get_context_data方法如果没有额外的上下文处理逻辑,可以直接删除,由父类方法默认处理;如果有其他逻辑,保留正常返回上下文即可:

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    # 其他上下文构建逻辑(如需要)
    return context

为什么这样更合理

  • get_object是DetailView等视图获取数据对象的标准入口,在这里做权限校验符合Django视图的执行流程。
  • 抛出Http404异常是Django处理资源不可访问的标准方式,能自动生成规范的404响应。
  • 分离了权限校验与上下文构建的职责,代码逻辑更清晰、易维护。

内容的提问来源于stack exchange,提问作者whoami0605

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 17:10:31