在Django的TEMPLATE_DIRS中使用外部URL
Django的设置文件Settings.py中的TEMPLATE_DIRS需要使用Unix风格的斜杠。
因此,当我在视图中调用
get_template('some/template.html')
时,结果总是从根目录开始,这导致调用了
/home/username/projectname/public/some/template.html
问题是我想使用托管在完全不同网站上的模板。对于其他设置字段(比如MEDIA_URL和STATIC_URL),这没有问题,它们可以接受绝对的http路径。
给定一个http路径,
TEMPLATE_DIRS ('http://example.com/',)
在Settings.py中会强制
get_template('some/template.html')
在视图中尝试查找
/home/username/projectname/public/http://example.com/some/template.html
我尝试这样绕过这个问题
TEMPLATE_DIRS ('../../../../http://example.com/',)
但它仍然强制加上一个前导斜杠,所以我得到的是"/http://example.com",这没什么用。
我有几个问题:
- 有没有办法让它从另一个服务器拉取模板文件?
- 考虑到模板文件需要为视图处理,这样做可行吗?
- 有没有可能创建一个替代' django.template.loaders.filesystem.Loader'的东西,不需要Unix风格的斜杠?
3 个回答
- 不 - 你无法通过http从另一个服务器获取文件。
- 是的 - 你可以创建一个新的类,继承django.template.loaders.filesystem.Loader,并适当地修改load_template_source方法,这样就可以通过http加载模板了。
一旦你完成了第三步,那么第二步的答案就是“是的” - 这样做是可行的 - 最终Django的模板语言并不在乎文件来自哪里,只要格式正确就行。
不过,这样加载模板的方式似乎效率很低,更可能有更好的方法来实现同样的效果。
你不能这样做。
这和路径名称没有关系。其实是因为文件系统模板加载器需要从文件系统中加载东西,所以才叫这个名字。
这和MEDIA_URL的情况完全不同:MEDIA_URL只是把一个路径加到你的HTML里,然后浏览器会去加载这个路径的内容。Django并不关心那个文件放在哪里;实际上,如果你给它一个不是URL的文件路径(也就是没有通过某个网络服务器提供的路径),它根本就无法工作。
不过,你可以写一个模板加载器,从另一个服务器获取模板。模板加载器是可以插拔的——你只需要把新加载器的名字放到TEMPLATE_LOADERS设置里。这个加载器本身需要使用像urllib.urlopen
这样的东西,从外部服务器获取模板。
但在你这么做之前,请仔细考虑。这意味着每一个模板请求现在都需要先调用外部服务器,才能提供页面。在一个典型的模板中,如果它扩展了其他模板并包含了一些模板标签的调用,这可能需要五到十次的调用。而且,与媒体文件不同,这个过程不能并行进行:页面在整个过程完成之前是无法提供的。这可能会让你的网络服务器变得非常非常慢。
我不知道你为什么觉得需要这样做。模板是你应用代码的一部分,所以它们通常和你的Python代码放在同一个服务器上。如果你真的有理由把它们放在外面,一个解决方案可能是通过像sshfs这样的方式,把外部文件系统挂载到你的网络服务器上。不过,这样做仍然可能会很慢。再想想吧。
如果你不想使用模板目录,其实可以不必使用。如果你的服务器可以提供模板文件,你可以直接通过 urllib2
从远程获取这些文件,然后手动创建和渲染模板。
import urllib2
from django.template import Context, Template
tpl_html = urllib2.urlopen("http://mysite.com")
tpl = Template(tpl_html)
return tpl.render(Context({
'some_variable' : 'some_val',
})
不过,如果你打算这么做,就得加一些缓存,因为每次使用这个模板时,你都需要发起一次外部请求。另一种方法是写一个自定义加载器,但这样也会遇到同样的问题。