django:RequestContextがcontext_instanceとして設定されているのはなぜですか?
-
06-07-2019 - |
質問
ほとんどのドキュメントが推奨しているようです:
template_values = {}
template_values["foo"] = "bar"
return render_to_response(path, template_values, context_instance=RequestContext(request)
使用しない理由:
template_values = RequestContext(request)
template_values["foo"] = "bar"
return render_to_response(path, template_values)
解決
RequestContext
は dict
を継承しないため、 dict
のすべてのメソッドを実装する保証はありません(そして、 't)、およびdictで動作する関数も機能しない可能性があります。最後に、理由はありません。実装が変更される可能性のある不透明なオブジェクトと考える方が良いでしょう。 dict
を使用してテンプレートのコンテキストを提供すると、 RequestContext
のすべての利点があり、欠点はありません。
更新
より少ない定型コードを生成するために、ここで使用する2つのユーティリティ関数を示します。プロジェクトのベースにあるshortcuts.pyファイルにそれらを置きます。
from django.template import RequestContext
def render_template(request, template, data=None):
"Wrapper around render_to_response that fills in context_instance for you."
response = render_to_response(template, data,
context_instance=RequestContext(request))
return response
def boilerplate_render(template):
"Factory function for creating simple views that only forward to a template"
def view(request, **kwargs):
response = render_template(request, template, kwargs)
return response
return view
使用法:
def my_view(request):
# Do stuff here...
return render_template(request, 'my_template.html', {'var1': 'value', etc..})
my_view2 = boilerplate_render('my_template2.html') # Takes no context parameters
他のヒント
「ボイラープレートコード」に関しては、これはすでにDjangoに組み込まれています。汎用ビューを使用してください:
from django.views.generic.simple import direct_to_template
def my_view(request):
# Do stuff here...
return direct_to_template(request, 'my_template.html', {'var1': 'value', etc..})
しばらくの間、Djangoボイラープレートに頭を叩いたようです。 Djangoには、テンプレートレンダリング用に(少なくとも)3つの非常によく似た機能があり、それぞれにさまざまな程度のショートカットがあります。
django.shortcuts.render_to_response
django.template.loader.render_to_string
django.views.generic.simple.direct_to_template
これらのうち少なくとも2つ(おそらくrender_to_responseとdirect_to_template)は、単一の、あまりボイラープラッシュではないショートカットにリファクタリングできるようです。
django.views.generic.simple.direct_to_template
はそれだけでほぼ十分ですが、残念ながらキーワード引数を params
dictに入れているため、ほとんどの用途と互換性がありません render_to_response
の( render_to_response
から direct_to_template
に切り替える場合、テンプレートのリファクタリングが必要になることがよくあります)。皮肉なことにdjango.shortcutsにある render_to_response
は、よく考えられたショートカットではありません。キーワード引数をテンプレートパラメータに変換し、 context_instance
引数が長すぎて...を入力するには長すぎます。
より便利なショートカットを試しました。 * request_and_template_and_params
を使用して、テンプレートパラメータ名と位置引数名の間の衝突を防ぐことに注意してください。
def render(*request_and_template_and_params, **kwargs):
"""Shortcut for rendering a template with RequestContext
Takes two or three positional arguments: request, template_name, and
optionally a mapping of template parameters. All keyword arguments,
with the excepiton of 'mimetype' are added to the request context.
Returns a HttpResponse object.
"""
if len(request_and_template_and_params) == 2:
request, template_name = request_and_template_and_params
params = kwargs
else:
request, template_name, params = request_and_template_and_params
params = dict(params) # copy because we mutate it
params.update(kwargs)
httpresponse_kwargs = {'mimetype': params.pop('mimetype', None)}
context = RequestContext(request, params)
return HttpResponse(loader.render_to_string(
template_name, context_instance=context), **httpresponse_kwargs)
このソリューションを見つけたばかりですこちらおよび私はそれを少しだけ修正します:
def render_to(template_name):
def renderer(func):
def wrapper(request, *args, **kw):
output = func(request, *args, **kw)
if not isinstance(output, dict):
return output
return render_to_response(template_name, output,
context_instance=RequestContext(request))
return wrapper
return renderer
@render_to('my_template.html')
def my_view(request):
# View code here...
return some_dict
「ボイラープレート」までコード、urls.pyのテンプレートにレンダリングできます
例:
url(r'^about/, direct_to_template, {'template': 'about.html',}),