将请求传递给自定义Django模板加载器

时间:2014-04-12 11:37:12

标签: django django-templates

我想为我的Django应用程序编写自定义模板加载器,该应用程序根据作为请求一部分的密钥查找特定文件夹。

让我进一步了解更多细节。假设我将在每个请求上获取一个密钥(我使用中间件填充)。

示例:request.key可以是'india'或'usa'或'uk'。

我希望我的模板加载器能够查找模板“templates/<key>/<template.html>”。所以当我说{% include "home.html" %}时,我希望模板加载器根据请求加载“templates / india / home.html”或“templates / usa / home.html”或“templates / uk / home.html” 。

有没有办法将请求对象传递给自定义模板加载器?

2 个答案:

答案 0 :(得分:4)

我一直在寻找相同的解决方案,经过几天的搜索,决定使用threading.local()。只需在HTTP请求处理期间使请求对象全局化! 开始从画廊扔掉腐烂的番茄。

让我解释一下:

从Django 1.8开始(根据开发版本文档)&#34; dirs&#34;将弃用所有模板查找函数的参数。 (ref)

这意味着除了请求的模板名称和模板目录列表之外,没有传递给自定义模板加载器的参数。如果您想访问请求网址中的参数(甚至是会话信息),您必须&#34;伸出&#34;进入其他一些存储机制。

import threading
_local = threading.local()

class CustomMiddleware:

    def process_request(self, request):
         _local.request = request

def load_template_source(template_name, template_dirs=None):
    if _local.request:
        # Get the request URL and work your magic here!
        pass

在我的情况下,它不是我直接访问的请求对象,而是应该呈现模板的网站(我正在开发SaaS解决方案)。

答案 1 :(得分:2)

要查找要渲染的模板,Django使用get_template方法,该方法只获取template_name和可选dirs参数。所以你无法在那里真正传递请求。

但是,如果您自定义render_to_response函数以传递dirs参数,则应该能够执行此操作。

例如(假设你像大多数人一样使用RequestContext):

from django import shortcuts
from django.conf import settings

def render_to_response(template_name, dictionary=None, context_instance=None, content_type=None, dirs):
    assert context_instance, 'This method requires a `RequestContext` instance to function'
    if not dirs:
        dirs = []
    dirs.append(os.path.join(settings.BASE_TEMPLATE_DIR, context_instance['request'].key)
    return shortcuts.render_to_response(template_name, dictionary, context_instance, content_type, dirs)