我想使用Django模板变量渲染一些静态文件(特别是* .js)。我相信这是一个常见的用例,尤其是在做任何AJAX-y时;我不想在我的.js文件中硬编码AJAX网址,只是想在我的.html文件中对它们进行硬编码。 Buuuut当然我不希望那些静态文件在每个客户端请求都必须通过模板引擎运行,因为这会很慢。我指的是诸如URL(在编译/部署之后不会改变)或静态(非db)模型属性之类的东西。 (我想有些用例可能会在运行时更改这些内容 - 毕竟这是Python,但我认为它们并不常见)。对于一些可能的模板变量(例如模型字段),当然必须在客户端请求时呈现文件,但这不是我所说的。
因此,通过模板引擎渲染一些静态文件,对于可能的模板变量的子集,可能与collectstatic
同时进行渲染是不合理的?
据我所知,目前情况并非如此。要明确的是,我正在寻找的是在编译/部署时通过模板引擎呈现静态文件的解决方案,以便在“客户端请求时”它们实际上是普通的旧静态文件。
这种方法可以避免这些黑客攻击:
免责声明:
所以:
collectstatic
(就像一个pre-collectstatic钩子),允许人们在“收集”它们之前通过模板引擎渲染某些静态文件?修改: 还没有回复......这是一个非常愚蠢的问题,我错过了一些明显的东西吗?如果是这样......继续告诉我......
答案 0 :(得分:3)
Django有几个用于相同目的的框架:django-pipeline,django-assets等,它们集成了不同的静态文件处理策略,配置有不同程度的难度。
我使用外部工具 - Grunt(它需要node.js) - 用于collectstatic
之后的资产后处理。它更容易,并且有很多plugins用于任何目的(源验证,css / js /图像缩小,合并,测试等)。
可以使用覆盖的post_process方法通过自定义静态文件存储挂钩collectstatic
。
示例/ settings.py
STATIC_ROOT = 'assets'
STATICFILES_STORAGE = 'example.storage.MyStaticFilesStorage'
示例/ storage.py
import os
from django.contrib.staticfiles.storage import StaticFilesStorage
from django.core.files.base import ContentFile
from django.template import Template, Context
class MyStaticFilesStorage(StaticFilesStorage):
def post_process(self, paths, dry_run=False, **options):
# don't even dare to process the files if we're in dry run mode
if dry_run:
return
js_template_data = {'foo': 'bar'} # template variables
js_template_extension = '.jst'
js_extension = '.js'
for original_name, (storage, path) in paths.items():
processed = False
saved_name = original_name
original_path, original_extension = os.path.splitext(original_name)
if original_extension == js_template_extension:
with storage.open(path) as original_file:
saved_name = original_path + js_extension
if hasattr(original_file, 'seek'):
original_file.seek(0)
original_source = original_file.read()
c = Context(js_template_data)
saved_source = Template(original_source).render(c)
self.delete(saved_name)
self.delete(original_name)
self._save(saved_name, ContentFile(saved_source))
processed = True
yield original_name, saved_name, processed
答案 1 :(得分:3)
解决问题的一种完全不同的方法是询问您是否确实需要在javascript中获取这些网址 - 相反,Javascript是否可以从HTML中的数据属性中获取网址?
换句话说,你可能想要:
<强> homepage.html 强>:
<div id="pop-up-modal">pop me up</div>
<强> homepage.js 强>:
$("#pop-up-modal").click(function {
$.ajax("{% url 'some-class-name %}")
...
});
通常可以更直接地执行以下操作:
<强> homagepage.html 强>:
<div id="pop-up-modal" data-popurl="{% url 'some-class-name' %}">pop me up</div>
<强> homepage.js 强>:
$("#pop-up-modal").click(function {
$.ajax($(this).data('popurl'))
...
});
答案 2 :(得分:1)
答案 3 :(得分:0)
你没有疯。我也对此感到沮丧,并发现自己在为我处理的每个新 Django 项目编写一些东西。我认为缺乏直接解决方案的原因是这是特大干旱的骨干。对这些东西进行硬编码并称之为一天是非常容易的。这和两个最常见的用例涉及从另一种语言的代码生成一种语言的代码,这往往被视为可疑。
我最近发布了一个新的 Django 包 django-render-static,它一般地解决了这个问题。它搭载在 Django 现有的模板引擎基础架构上。一个名为 render_static
的管理命令应该在 before collectstatic
之前运行。此命令将查找在设置中注册(或作为参数传递)的模板,并将它们呈现到磁盘上的静态文件位置。然后它们可用于您配置的任何普通静态文件打包管道。
我确信还有更多用例,但我发现的两个最常见的是在静态 JavaScript 中提供一个 reverse
实用程序,它相当于 Django 和自动翻译定义的 Python 结构(即选择字段)转换为 JavaScript。该应用提供了两种模板标签。
JavaScript url 反转代码保证在功能上等同于 Django 的 reverse
函数。因为it's been well documented。