考虑一下:
return render(request, 'index.html', {..context..})
return render_to_response('index.html', {..context..})
一方面,render
更清洁,更py。另一方面,你使用request
作为你的第一个参数,我觉得这个参数多余且令人困惑。所以我开始怀疑更大的差异......
根据the docs:
render()与使用a调用render_to_response()相同 context_instance参数,强制使用RequestContext。
所以区别仅在于使用RequestContext。那么RequestContext有什么重要意义呢?我们来看看docs again:
一个特殊的Context类[...]的行为略有不同 正常的django.template.Context。第一个区别是它需要 一个HttpRequest作为它的第一个参数。
确定。这根本不重要
第二个区别是它会自动填充上下文 根据您的TEMPLATE_CONTEXT_PROCESSORS,使用一些变量 设置[...]除了这些之外,RequestContext始终使用 django.core.context_processors.csrf [...]故意硬编码 在TEMPLATE_CONTEXT_PROCESSORS中无法关闭 设置。
所以这是重要的部分 - 确保所有上下文处理器正常工作,重点是csrf。所以,回到我的第一个例子,这些实际上是相同的:
return render(request, 'index.html', {...})
return render_to_response('index.html', {...}, context_instance=RequestContext(request))
现在,第二个例子显然要糟糕得多,整个事情似乎过于复杂。所以我的重要问题是为什么要使用render_to_response
?为什么不弃用呢?
浮现在脑海中的其他问题:
RequestContext
作为默认值? request
作为参数传递?这非常多余。我发现a blog post显示了如何将render_to_response变成一个易于使用的装饰器。我们不能用render
做类似的事情吗?render
来自django 1.3 specifically to address the problems with render_to_response,而everyone agrees you shouldn't use render_to_response
我知道这似乎有点偏离主题,但我希望得到的答案可以解释为什么render_to_response
留下来和\或使用render_to_response
的用例的例子首选超过render
(如果有的话)
答案 0 :(得分:30)
大多数应用使用render_to_response
,因为从一开始就是Django 1.3,这是默认的推荐选项。两者共存的原因是历史性的,弃用render_to_response
将迫使大量代码被重写,这在次要版本中是不礼貌的。但是in this django-developer thread他们说可以在2.0的弃用时间表中包含。
以下是Django核心开发人员之一Russell Keith-Magee的引用。 Keith-Magee回答了Jacob Kaplan-Moss发布的问题,Jacob Kaplan-Moss是另一位提出贬值问题的Django贡献者render_to_response
:
我认为我们应该弃用render_to_response()以支持render()。 render_to_response()只是渲染(request = None,...),对吗?任何 有理由保持两者?除了代价流失之外,没有特别的理由要保持这两种情况。
Keith-Magee回答:
这是我在2.0上弃用没问题的 安排,但迁移每次使用render_to_response() 接下来的18个月/ 2个版本似乎是一个强制执行的极端措施 维护render_to_response()时没有整个用户群 采取任何实际的努力。
没有人一直在讨论这种弃用,但我想你的问题的答案是:没有技术原因,只是他们的意图是不强制对次要(至少没有主要)版本的所有代码库进行更新。
答案 1 :(得分:8)
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)
Subclassing Context: RequestContext
部分中的注意
如果您使用Django的
render_to_response()
快捷方式使用字典内容填充模板,默认情况下您的模板将传递Context
个实例(而不是RequestContext
)< / p>
从上面的代码render_to_response
方法调用方法loader.render_to_string
,this line中选中了context_instance
参数。
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()
与render_to_response()
的调用相同,context_instance
参数会强制使用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背后的代码实际上是如何工作的,那么最后一个问题不需要答案。