Django 1.11.17 TypeError:'上下文必须是字典而不是上下文',除了它是字典

Posted

技术标签:

【中文标题】Django 1.11.17 TypeError:\'上下文必须是字典而不是上下文\',除了它是字典【英文标题】:Django 1.11.17 TypeError: 'context must be a dict rather than Context', except IT IS A DICTDjango 1.11.17 TypeError:'上下文必须是字典而不是上下文',除了它是字典 【发布时间】:2019-05-08 11:39:37 【问题描述】:

我最近从 Django 1.9 切换到 1.11.17,有一件事让我很困扰。有这个错误说

TypeError at /somepath
context must be a dict rather than Context

抛出它的那一行是:

return render(request=request, template_name="mytemplate.html", context="form": form, "update": updateType)

关于 SO 有很多答案,人们使用 RequestContext 或 Context 而不是 dict 来表示 context 并且切换到 dict 可以解决他们的问题。但不适合我。在这里,我很确定我的context 实际上是一个字典。如果我将其更改为:

return render(request=request, template_name="mytemplate.html", context=)

错误消失了,但显然稍后会导致另一个错误。你们知道我在这里做错了什么吗?

编辑: 我的进口:

from django.shortcuts import render, render_to_response
from django.template.context import RequestContext, Context

我尝试过 bot renderrender_to_response 具有类似的效果。也使用 Context 或 RequestContext 给出了类似的错误。

EDIT2:更多代码供参考

from django.http import (
    HttpResponseRedirect,
    HttpResponseBadRequest,
)
from django.shortcuts import render, render_to_response
from django.template import RequestContext, Context
from django.utils.html import escape

# some more imports, but from local files, not django

def update_my_template(request):
    user = request.user
    # preform some checks for user
    ...

    if request.method == "GET":
        updateType = request.GET.get("id")
        if updateType:
            form = None
            if updateType == "something":
                form = SomeForm(user)
            if updateType == "something else":
                form = DifferentForm()
            if form is None:
                return HttpResponseRedirect("/somepage")

            # This was the code that worked in 1.9
            rctx = RequestContext(
                request, "form": form, "update": updateType
            )
            return render_to_response("mytemplate.html", rctx)



    # some different cases, but the error is thrown already
...

这些都不起作用:

dictctx = "form": form, "update": updateType
return render(request=request, template_name="mytemplate.html", dictctx)

.

ctx = Context("form": form, "update": updateType)
return render(request=request, template_name="mytemplate.html", ctx)

.

ctx = Context("form": form, "update": updateType)
return render(request=request, template_name="mytemplate.html", ctx.flatten())

.

rctx = RequestContext(request, "form": form, "update": updateType)
return render_to_response("mytemplate.html", rctx.flatten())

【问题讨论】:

只是为了确保我的假设是正确的,您可以编辑您的问题并添加您对Contextrender 的导入吗? 当然,一秒钟 如果您将from django.template.context 更改为from django.template,我下面的代码是否有效? 不幸的是,from django.template.contextfrom django.template 似乎没有任何区别 【参考方案1】:

render 的逻辑有所不同,具体取决于您传递给render 的内容:

def render(self, context):
        "Display stage -- can be called many times"
        with context.render_context.push_state(self):
            if context.template is None:
                with context.bind_template(self):
                    context.template_name = self.name
                    return self._render(context)
            else:
                return self._render(context)

看起来您可以将参数 template_name 更改为 name 但您的对象没有 context.render_context 值,这就是为什么创建和使用实例会更好的原因Context

https://docs.djangoproject.com/en/1.11/_modules/django/template/base/#Template.render

文档显示传递了 Context 的实际实例,因此我建议您在代码中这样做,而不仅仅是传递字典:

>>> from django.template import Context, Template
>>> template = Template("My name is  my_name .")

>>> context = Context("my_name": "Adrian")
>>> template.render(context)
"My name is Adrian."

>>> context = Context("my_name": "Dolores")
>>> template.render(context)

所以修复代码的最简单方法是这样的:

from django.template import Context
...
return render(request=request, template_name="mytemplate.html", context=Context("form": form, "update": updateType))

【讨论】:

我试过这个没有效果: ctx = Context("form": form, "update": updateType) return render(request=request, template_name="mytemplate.html", context =ctx) 你见过this 吗?它基本上是说在将任何RequestContext 对象传递给渲染之前调用.flatten() 是的,在问我之前已经尝试过其他答案:(同样的错误 我想这一定是一些超级愚蠢的错误,因为我已经尝试了所有可能性,而且我的代码看起来与其他 SO 答案中发布的代码相同。 您能否编辑您的答案并从该文件中添加尽可能多的代码?我唯一能想到的是,它可能是文件中的其他内容【参考方案2】:

始终在参数中传递变量/值。但你同时给予两者。试试这个,...

返回渲染(request=request, template_name="mytemplate.html", "form": 表单, "update": updateType)

或者

context="form": form, "update": updateType 返回 渲染(request=request, template_name="mytemplate.html",context)

【讨论】:

我看不出您的第一个解决方案与我的解决方案有什么区别。另外我已经尝试过第二个,没有区别:/ @Devligue 在我的第一个解决方案中,我只是传递了元组,而在我的第二个解决方案中,我只是传递了元组类型的变量,但不幸的是你同时传递了这两个。这是一个逻辑错误 但是你确实看到你在关键字参数之后传递了位置参数?这段代码甚至不能在 python 中运行,它立即抛出错误【参考方案3】:

好的,经过更多挖掘(在“未解决”问题中)我找到了this gem。是的,这就是我的问题的解决方案。基本上我的mytemplate.html 中有form|bootstrap 行,这是造成这种情况的原因。

更好的是,将 django-bootstrap-form 更新到 3.4 版让我可以保留 form|bootstrap 并摆脱错误。

【讨论】:

以上是关于Django 1.11.17 TypeError:'上下文必须是字典而不是上下文',除了它是字典的主要内容,如果未能解决你的问题,请参考以下文章

django:TypeError:'tuple'对象不可调用

Django TypeError - TypeError: issubclass() arg 1 必须是一个类

Django:“TypeError:[] 不是 JSON 可序列化的”为啥?

Django 预览,TypeError:'str' 对象不可调用

Django异常中间件:TypeError:object()不带参数

Django ConnectionAbortedError + TypeError + AttributeError