![](/img/trans.png)
[英]Error “TypeError context must be a dict rather than Context” on Django 1.11
[英]Django 1.11 context processor error: TypeError: context must be a dict rather than RequestContext'
我不知道為什么我在Django 1.11和RenderContext
遇到問題。 我真的需要這里的幫助。 這是我從1.11的官方文檔中獲取的代碼:
from django.http import HttpResponse
from django.template import RequestContext, Template
from django.template import loader
def ip_address_processor(request):
return {'ip_address': request.META['REMOTE_ADDR']}
def view_2(request):
template = loader.get_template('template2.html')
ctx = RequestContext(request, {
'title': 'Your IP Address',
}, [ip_address_processor])
return HttpResponse(template.render(ctx))
而我的簡單模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Test
{{ title }}: {{ ip_address }}
</body>
</html>
這將導致以下錯誤:
Internal Server Error: /view2/
Traceback (most recent call last):
File "C:\Python27\lib\site-packages\django\core\handlers\exception.py", line 41, in inner
response = get_response(request)
File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\null\PycharmProjects\project1\project1\views.py", line 48, in view_2
return template.render(c)
File "C:\Python27\lib\site-packages\django\template\backends\django.py", line 64, in render
context = make_context(context, request, autoescape=self.backend.engine.autoescape)
File "C:\Python27\lib\site-packages\django\template\context.py", line 287, in make_context
raise TypeError('context must be a dict rather than %s.' % context.__class__.__name__)
TypeError: context must be a dict rather than RequestContext.
[07/Aug/2017 23:52:49] "GET /view2/ HTTP/1.1" 500 72701
這對我來說很奇怪,因為以下代碼有效:
from django.http import HttpResponse
from django.template import RequestContext, Template
from django.template import loader
def ip_address_processor(request):
return {'ip_address': request.META['REMOTE_ADDR']}
def view_2(request):
template = Template('{{ title }}: {{ ip_address }}')
ctx = RequestContext(request, {
'title': 'Your IP Address',
}, [ip_address_processor])
return HttpResponse(template.render(ctx))
通過覆蓋Template來對模板進行硬編碼可以很好地工作,但是用django.template.loader.get_loader導入模板卻不能? 我真的很茫然。
我究竟做錯了什么? 模板正在做完全相同的事情。 這確實使我從1.11開始退縮。 過去,您可以在Django 1.8中傳遞一個context_instance,它才起作用。 即使使用docs.djangoproject.com上記錄的示例,我似乎也無法在1.11中運行任何上下文處理程序。 僅當我調用Template並通過對它進行硬編碼將其傳遞給我時,它才有效。
正如The_Cthulhu_Kid在評論中說的那樣 ,Django 1.11不贊成在非字典上下文中傳遞:
我想出一個簡單的例子,如果有人想出您將如何在1.11中處理內容處理器
我將上面的示例代碼更改為:
def ip_address_processor(request):
return {'ip_address': request.META['REMOTE_ADDR'], 'ua': request.META['HTTP_USER_AGENT']}
def view_2(request):
template = loader.get_template('template2.html')
proc_ex = ip_address_processor(request)
context = {'ua': proc_ex.get('ua'),
'ip_address': proc_ex.get('ip_address'),
'title': 'TEST'}
return HttpResponse(template.render(context))
和模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ title }}: {{ ip_address }}
User-Agent: {{ ua }}
</body>
</html>
您也可以這樣做,以免必須將鍵與ip_address_processor函數對齊:
def ip_address_processor(request):
return {'ip_address': request.META['REMOTE_ADDR'], 'ua': request.META['HTTP_USER_AGENT']}
def view_2(request):
template = loader.get_template('template2.html')
proc_ex = ip_address_processor(request)
proc_ex.update({'title': 'test2'})
return HttpResponse(template.render(proc_ex))
看起來這里的關鍵是只給它喂字典,它很高興。
基本上,您面臨的問題是在Django 1.11中禁止非字典上下文。
為了與多個模板引擎兼容,
django.template.backends.django.Template.render()
必須接收上下文字典,而不是Context
或RequestContext
。 如果您要傳遞兩個類中的任何一個,請改為傳遞字典-這樣做與舊版本的Django向后兼容。
您應該使用render
而不是返回HttpResponse
,因此可以按以下方式更新代碼。 注意,它傳遞的是dict而不是RequestContext
類型的對象作為上下文。
def ip_address_processor(request):
return {'ip_address': request.META['REMOTE_ADDR']
'ua': request.META['HTTP_USER_AGENT']}
def view_2(request):
context = ip_address_processor(request)
context.update({'title': 'test2'})
return render(request, 'template2.html', context)
render
是一個快捷方式,它將以模板名稱作為參數,然后使用給定的參數渲染此模板,然后返回帶有渲染主體的HttpResponse
。
HttpResponse
不會在后台執行Django之類的工作,因此,如果要返回渲染的Django模板,則需要手動執行此操作,然后將結果傳遞給HttpResponse
然后再返回。 (有關更多信息,請查看此問題及其答案 )
嘗試這個:
from django.http import HttpResponse
from django.template import Template
from django.template import loader
def ip_address_processor(request):
return {'ip_address': request.META['REMOTE_ADDR']}
def view_2(request):
template = loader.get_template('template2.html')
ctx = request.GET.copy().dict()
ctx.update({
'title': 'Your IP Address',
})
ctx.update(ip_address_processor(request))
return HttpResponse(template.render(ctx))
request.GET
現在返回一個只讀的QueryDict
對象。 為了使其可修改,您必須使用.copy()
獲得讀寫副本。 然后,您必須使用.dict()
將其轉換為常規的Python字典。 render()
方法不會接受它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.