渲染模板时是否有提供加载器列表的低级方法,而不是总是让Django使用该设置?
我想只为几个视图使用自定义模板加载器实例(我有我的理由)。
答案 0 :(得分:3)
看起来你必须自己编写一些代码才能完成它。让我们来看看加载模板的常规代码路径,如果你使用render_to_response
,那么the source的相关部分是:
return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
这是对django.template.loader.render_to_string
的调用,它会通过其他一些函数,最终会调用find_template
。
第一次调用find_template
时,会根据template_source_loaders
初始化全局settings.TEMPLATE_LOADERS
缓存。所以看起来你不能传递额外的参数或类似的东西。
一种可能性是在该视图的持续时间内向django.template.loader.template_source_loaders
添加一些加载器。我不知道这是否会引起其他问题;它感觉很脏,但如果它有效,它会很容易。 (只需制作一个视图装饰器即可。)
如果您不想这样做,看起来您必须使用自己的代码复制render_to_string
的工作(如果您确定要使用每个视图模板加载器) ,我为了这个问题而接受作为前提,但我打赌其实并不是必要的)。那里没有那么多代码,如果您事先知道要使用的特定加载器和单个模板名称,那实际上非常简单。 (这是未经测试的,但可能会起作用。)
def render_to_response_with_loader(loader, name,
dictionary=None, context_instance=None, mimetype=None, dirs=None):
# from find_template
t, display_name = loader(name, dirs)
# from get_template
if not hasattr(t, 'render'):
# template needs to be compiled
t = django.template.loader.get_template_from_string(t, origin, template_name)
# from render_to_string
if not context_instance:
rendered = t.render(Context(dictionary))
else:
# Add the dictionary to the context stack, ensuring it gets removed again
# to keep the context_instance in the same state it started in.
context_instance.update(dictionary)
try:
rendered = t.render(context_instance)
finally:
context_instance.pop()
# from render_to_response
return HttpResponse(rendered, mimetype=mimetype)
如果您想支持多个可能的加载器或可能的文件名列表,只需复制django.template.loader中的相关代码。
答案 1 :(得分:1)
我最后通过修改template_source_loaders来做这件事,正如Dougal建议的那样。就像他说的那样,我不确定这是否安全(可能会造成竞争条件吗?),但它现在适用于我的特殊情况。通过Dougal建议的其他方式这样做的好处是它确保{%extends%}和{%include%}也使用修改后的加载器。这是我的带有自定义加载器的render_to_string:
def render_to_string_with_loader(*args, **kwargs):
""" Call render_to_string using ReportTemplateLoader to find templates. """
import django.template.loader as loader
old_loaders = settings.TEMPLATE_LOADERS
settings.TEMPLATE_LOADERS = ('main.loaders.ReportTemplateLoader',)
loader.template_source_loaders = None # force refresh from settings
try:
out = render_to_string(*args, **kwargs)
finally:
# use finally make sure template errors can't mess up later requests
settings.TEMPLATE_LOADERS = old_loaders
loader.template_source_loaders = None