Ошибка обработчика контекста в Django 1.11: Ошибка типа: контекст должен быть dict, а не 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. Раньше вы могли передавать context_instance в Django 1.8, и это просто работало. Кажется, я не могу запустить ни одного Context Procesers в версии 1.11, даже используя пример, описанный на docs.djangoproject.com. Это работает только тогда, когда я вызываю Template и передаю свой шаблон через него путем жесткого кодирования.
2 ответа
Как сказал The_Cthulhu_Kid в комментарии, Django 1.11 не одобряет переход в недиктивный контекст:
https://docs.djangoproject.com/en/1.11/releases/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()
. Затем вам нужно преобразовать его в обычный словарь Python, используя.dict()
. Вrender()
иначе метод не примет.