在 Django 的 TEMPLATE_DIRS 中使用外部 URL

Posted

技术标签:

【中文标题】在 Django 的 TEMPLATE_DIRS 中使用外部 URL【英文标题】:Using external URLs in Django's TEMPLATE_DIRS 【发布时间】:2012-01-02 07:48:07 【问题描述】:

Settings.py 中 Django 的 TEMPLATE_DIRS 调用 unix 样式的斜线。

因此,当我打电话时

get_template('some/template.html')

在视图中,结果总是从根开始,并导致调用

/home/username/projectname/public/some/template.html

问题是我想使用托管在完全不同网站上的模板。这适用于其他 Settings.py 字段(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”,这是没用的。

我的问题:

    有没有办法欺骗它从 另一个服务器? 考虑到模板文件需要 处理视图? 是否可以创建一个不需要 unix 样式斜杠的 'django.template.loaders.filesystem.Loader' 的替代品?

【问题讨论】:

【参考方案1】:

你不需要使用模板目录是你不想。如果您有一个提供模板文件的服务器,您可以简单地使用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',
)

如果你要这样做,你必须合并一些缓存,因为每个使用这个模板的请求,你都需要发出一个外部请求。或者,您可以将其写入自定义加载程序,但它会受到相同的限制。

【讨论】:

这对我有用,在 return 声明中做了以下小改动:return HttpResponse(tpl.render(Context(...)))【参考方案2】:

你不能这样做。

它与路径名无关。只是文件系统模板加载器需要从文件系统加载东西,因此得名。

这与 MEDIA_URL 的情况完全不同:它只是在您的 HTML 中添加一个路径,然后您的浏览器会加载该路径。 Django 不在乎该文件的位置:尽管实际上相反,如果您向它传递一个不是 URL 的文件路径(即由某处的网络服务器提供服务),它将根本无法工作。

现在,您可以编写一个从另一台服务器获取其模板的模板加载器。模板加载器是可插入的 - 您只需将新加载器的名称放在 TEMPLATE_LOADERS 设置中。加载器本身需要使用urllib.urlopen 之类的东西从外部服务器获取模板。

但是在你这样做之前要仔细考虑。这意味着每个模板请求现在都需要调用外部服务器才能提供页面。在扩展其他模板并包含对包含的模板标签的调用的模板的典型情况下,可能是五个或十个调用。而且,与媒体文件不同,它不能并行完成:在整个过程完成之前不会提供页面。这可能会使您的网络服务器非常缓慢。

我不知道你为什么认为你需要这样做。模板是您的应用程序代码的一部分,因此它们通常与您的 Python 代码位于同一台服务器上。如果您确实有理由将它们保留在外部,一种解决方案可能是通过sshfs 之类的方式将外部文件系统安装到您的网络服务器上。不过,它仍然可能非常缓慢。再想一想。

【讨论】:

我想这样做的原因是非典型的,并且会随着部署而消失。即使 fcgi 被杀死并重新启动,我要部署到的服务器反映文件系统更改的速度也很慢。因此,我一直在 django 友好的 anydata.com 上进行开发。它更快更流畅,但有 10MB 的存储限制,所以为了避免达到这个限制,我一直在其他地方尽可能多地托管。尽管如此,您所说的还是有道理的,在这种情况下,绝对最好将相对较小的模板文件放在本地,而不是降低性能。谢谢。【参考方案3】:
    不 - 不可能诱骗它通过 http 从另一台服务器拉取文件 是的 - 你当然可以继承 django.template.loaders.filesystem.Loader (并通过适当地改变 load_template_source 方法),这样你就可以通过 http 加载模板

一旦你完成了 3,那么对 2 的答案就是肯定的——这将是可行的——最终 Django 的模板语言并不关心它从哪里获取文件,只要它采用正确的格式。

但是,这似乎是一种非常低效的加载模板的方式,更有可能有更好的方式来实现相同的结果。

【讨论】:

以上是关于在 Django 的 TEMPLATE_DIRS 中使用外部 URL的主要内容,如果未能解决你的问题,请参考以下文章

如何从 django 交互式 shell 打印 TEMPLATE_DIRS 的值?

Django 1.4(MEDIA_ROOT、STATIC_ROOT、TEMPLATE_DIRS)

Django模板路径设置:templates,TEMPLATE_DIRS,TEMPLATES

django大全

Django 模板大纲

Djang DJANGO_SETTINGS_MODULE