太长了;没读过
When context processors are applied
当您使用RequestContext 时,首先添加您直接提供的变量,然后是上下文处理器提供的任何变量。这意味着上下文处理器可能会覆盖您提供的变量,因此请注意避免与上下文处理器提供的变量名称重叠。
让我们先看看render_to_response和render这两个方法是如何定义的。
def render_to_response(*args, **kwargs):
"""
Returns a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments.
"""
httpresponse_kwargs = {'content_type': kwargs.pop('content_type', None)}
return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
def render(request, *args, **kwargs):
"""
Returns a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments.
Uses a RequestContext by default.
"""
httpresponse_kwargs = {
'content_type': kwargs.pop('content_type', None),
'status': kwargs.pop('status', None),
}
if 'context_instance' in kwargs:
context_instance = kwargs.pop('context_instance')
if kwargs.get('current_app', None):
raise ValueError('If you provide a context_instance you must '
'set its current_app before calling render()')
else:
current_app = kwargs.pop('current_app', None)
context_instance = RequestContext(request, current_app=current_app)
kwargs['context_instance'] = context_instance
return HttpResponse(loader.render_to_string(*args, **kwargs),
**httpresponse_kwargs)
难道没有更好的方法将 RequestContext 强制为默认值吗?
注意部分Subclassing Context: RequestContext
如果您使用 Django 的 render_to_response() 快捷方式来使用字典的内容填充模板,则默认情况下您的模板将被传递一个 Context 实例(而不是 RequestContext)
从上面的代码中,方法render_to_response 调用方法loader.render_to_string,其中context_instance 参数在this line 中被检查。
方法render_to_string的代码清单
def render_to_string(template_name, dictionary=None, context_instance=None,
dirs=None):
"""
Loads the given template_name and renders it with the given dictionary as
context. The template_name may be a string to load a single template using
get_template, or it may be a tuple to use select_template to find one of
the templates in the list. Returns a string.
"""
dictionary = dictionary or {}
if isinstance(template_name, (list, tuple)):
t = select_template(template_name, dirs)
else:
t = get_template(template_name, dirs)
if not context_instance:
return t.render(Context(dictionary))
# Add the dictionary to the context stack, ensuring it gets removed again
# to keep the context_instance in the same state it started in.
with context_instance.push(dictionary):
return t.render(context_instance)
我们不能用render做简单易用的装饰器吗?
我们可以为此编写装饰器,但您的问题是主观的。它是否易于使用很难说。这很大程度上取决于
有没有办法避免将请求作为参数传递?
render() 与使用context_instance 参数调用render_to_response() 相同强制使用RequestContext。
class RequestContext 定义为 in this line。
class RequestContext 的代码清单
class RequestContext(Context):
"""
This subclass of template.Context automatically populates itself using
the processors defined in TEMPLATE_CONTEXT_PROCESSORS.
Additional processors can be specified as a list of callables
using the "processors" keyword argument.
"""
def __init__(self, request, dict_=None, processors=None, current_app=None,
use_l10n=None, use_tz=None):
Context.__init__(self, dict_, current_app=current_app,
use_l10n=use_l10n, use_tz=use_tz)
if processors is None:
processors = ()
else:
processors = tuple(processors)
updates = dict()
for processor in get_standard_processors() + processors:
updates.update(processor(request))
self.update(updates)
如果您了解 Django 背后的代码实际上是如何工作的,那么最后一个问题不需要答案。