django: Warum ist Request als context_instance eingestellt?
-
06-07-2019 - |
Frage
Es scheint, die meisten Dokumentation empfiehlt:
template_values = {}
template_values["foo"] = "bar"
return render_to_response(path, template_values, context_instance=RequestContext(request)
Warum kann ich nicht verwenden:
template_values = RequestContext(request)
template_values["foo"] = "bar"
return render_to_response(path, template_values)
Lösung
RequestContext
erbt nicht von dict
, und als solcher nicht alle dict
Methoden garantiert implementieren (und es nicht) und alle Funktionen, die auf dicts arbeiten nicht funktionieren entweder. Schließlich gibt es keinen Grund zu; es ist besser, es ein undurchsichtiges Objekt, deren Implementierung ändern zu berücksichtigen. eine dict
Mit der Vorlage Zusammenhang die Vorteile und keine der Nachteile von RequestContext
hat alles zu bieten.
Update
weniger Standardcode zu erzeugen, sind hier zwei Nutzenfunktionen ich verwende. Ich habe sie in einer shortcuts.py Datei an der Basis meines Projektes.
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
Verbrauch:
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
Andere Tipps
In Bezug auf den „Kesselblech Code“, das ist schon in Django gebaut. Verwenden Sie einfach die allgemeine Ansicht:
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..})
Wurde schlug meinen Kopf auf Django vorformulierten für eine Weile jetzt. Django hat (mindestens) drei sehr ähnliche Funktionen für Template-Rendering, die jeweils mit einem unterschiedlichen Grad der shortcutedness:
django.shortcuts.render_to_response
django.template.loader.render_to_string
django.views.generic.simple.direct_to_template
Es scheint, dass mindestens zwei von diesen (wahrscheinlich render_to_response und direct_to_template) in einem einzigen, weniger boilerplatish Refactoring werden könnte, Verknüpfung.
ist django.views.generic.simple.direct_to_template
fast gut genug auf seinem eigenen, sondern bringt leider Schlüsselwort Argumente in einer params
dict, es unvereinbar mit dem meisten Anwendungen von render_to_response
machen (Vorlage Refactoring ist oft notwendig, wenn von render_to_response
Umstellung auf direct_to_template
). render_to_response
, die ironischerweise in django.shortcuts lebt, ist kaum eine gut durchdacht Verknüpfung. Es sollte Schlüsselwort Argumente Template-Parameter konvertieren und plump context_instance
Argument ist einfach zu lang ... oft zu geben.
Ich habe eine nützliche Abkürzung versucht. Beachten Sie die Verwendung von *request_and_template_and_params
zu Auseinandersetzungen zwischen Template-Parameter-Namen und Positions Argumente Namen zu verhindern.
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)
Ich habe gerade diese Lösung hier und i modificate es nur eine litle:
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
Im Anschluss an den „Kesselblech“ Code, Sie zu einer Vorlage in Ihrem urls.py machen könnten
Zum Beispiel:
url(r'^about/$', direct_to_template, {'template': 'about.html',}),