簡體   English   中英

Django 1.11上下文處理器錯誤:TypeError:上下文必須是字典而不是RequestContext'

[英]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不贊成在非字典上下文中傳遞:

https://docs.djangoproject.com/zh-CN/1.11/releases/1.11/#django-template-backends-django-template-render-prohibits-non-dict-context

我想出一個簡單的例子,如果有人想出您將如何在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()必須接收上下文字典,而不是ContextRequestContext 如果您要傳遞兩個類中的任何一個,請改為傳遞字典-這樣做與舊版本的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM