[英]Django: render staticfiles through template engine at deploy-time
I want to render some static files (*.js in particularly) using Django template variables.我想使用 Django 模板变量呈现一些静态文件(特别是 *.js)。 I believe this is a common use-case, especially when doing anything AJAX-y;
我相信这是一个常见的用例,尤其是在做任何 AJAX-y 时; I don't want to hardcode AJAX urls in my .js files any more than I want to hardcode them in my .html files.
我不想在我的 .js 文件中硬编码 AJAX url,就像我不想在我的 .html 文件中硬编码它们一样。 Buuuut of course I don't want those static files to have to run through the template engine at every client request because this will be slow.
当然,我不希望这些静态文件在每次客户端请求时都必须通过模板引擎运行,因为这会很慢。 I am referring to things like URLs (which do not change after compile/deploy) or static (non-db) model attributes.
我指的是 URL(在编译/部署后不会改变)或静态(非数据库)模型属性之类的东西。 (I suppose there are use cases where these things might be changed at run-time - this is Python, after all- but I think they are uncommon).
(我想有些用例可能会在运行时更改这些东西——毕竟这是 Python——但我认为它们并不常见)。 For some possible template variables (eg model fields), of course the file must be rendered at the time of the client request, but this is not what I'm talking about.
对于一些可能的模板变量(例如模型字段),当然必须在客户端请求时呈现文件,但这不是我要说的。
So wouldn't it make sense to render some of my static files through the template engine, for a subset of possible template variables, perhaps at the same time as collectstatic
?那么通过模板引擎渲染我的一些静态文件,对于可能的模板变量的子集,也许与
collectstatic
同时渲染是否有意义?
As far as I can tell this is not currently the case.据我所知,目前情况并非如此。 To be clear, what I am looking for is a solution to render static files through the template engine at compile/deploy-time so that at "client-request-time" they are in fact plain old static files .
需要明确的是,我正在寻找一种在编译/部署时通过模板引擎呈现静态文件的解决方案,以便在“客户端请求时”它们实际上是普通的旧静态文件。
Such an approach would avoid these hacks:这种方法将避免这些黑客:
Disclaimers:免责声明:
So:所以:
collectstatic
(like a pre-collectstatic hook) that would allow one to render certain static files through the template engine before "collecting" them?collectstatic
(如 pre-collectstatic 挂钩),允许人们在“收集”它们之前通过模板引擎呈现某些静态文件? EDIT : No responses yet...is this a really dumb question, and I'm missing something obvious?编辑:还没有回应......这是一个非常愚蠢的问题,我错过了一些明显的东西吗? If so...go ahead and let me know...
如果是这样......继续让我知道......
There are several frameworks for Django for same purpose: django-pipeline , django-assets , and etc. which integrates different static files processing strategies, with varying degrees of difficulty configuring. django有几个框架用于相同的目的: django-pipeline 、 django-assets等,它们集成了不同的静态文件处理策略,配置难度不同。
I use an external tool - Grunt (it requires node.js) - for asset post-processing after collectstatic
.我使用外部工具 - Grunt (它需要 node.js) - 在
collectstatic
之后进行资产后处理。 It is easier and has a lots of plugins for any purpose (source validation, css/js/images minification, merging, testing and etc.).它更容易,并且有很多用于任何目的的插件(源验证、css/js/图像缩小、合并、测试等)。
It is possible to hook in collectstatic
by a custom static files storage with overrided post_process method.可以使用覆盖post_process方法的自定义静态文件存储挂钩
collectstatic
。
example/settings.py示例/settings.py
STATIC_ROOT = 'assets'
STATICFILES_STORAGE = 'example.storage.MyStaticFilesStorage'
example/storage.py示例/存储.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
A completely different way to approach the problem would be to ask if you really need to get those URLs in javascript--instead, can the Javascript get the URLs from things like data attributes in your HTML?解决该问题的一种完全不同的方法是询问您是否真的需要在 javascript 中获取这些 URL——相反,Javascript 能否从 HTML 中的数据属性等内容中获取 URL?
In other words, you might have wanted:换句话说,您可能想要:
homepage.html :主页.html :
<div id="pop-up-modal">pop me up</div>
homepage.js :主页.js :
$("#pop-up-modal").click(function {
$.ajax("{% url 'some-class-name %}")
...
});
When it can often be more straightforward to do something like:什么时候做这样的事情通常会更直接:
homagepage.html :主页.html :
<div id="pop-up-modal" data-popurl="{% url 'some-class-name' %}">pop me up</div>
homepage.js :主页.js :
$("#pop-up-modal").click(function {
$.ajax($(this).data('popurl'))
...
});
I think that django-medusa would suit your needs.我认为django-medusa会满足您的需求。
By setting up a renderer and using the disk based backend, generating the static files would be as easy as:通过设置渲染器并使用基于磁盘的后端,生成静态文件将非常简单:
django-admin.py staticsitegen
You aren't crazy.你没疯。 I was frustrated by this as well and found myself hacking something together for each new Django project I tackled.
我也对此感到沮丧,并发现自己在为我处理的每个新 Django 项目编写一些东西。 I think the reason for the lack of direct solutions is that this is mega-drought bone DRY.
我认为缺乏直接解决方案的原因是这是特大干旱的骨干。 Its super easy to just hard code these things and call it day.
对这些东西进行硬编码并称之为一天是非常容易的。 This and the two most common use cases for this involve generating code in one language from code in another which tends to be viewed as suspect.
这和两个最常见的用例涉及从另一种语言的代码生成一种语言的代码,这往往被视为可疑。
I've recently published a new Django package django-render-static that solves this problem generically.我最近发布了一个新的 Django 包django-render-static ,它一般地解决了这个问题。 It piggy-backs on Django's existing template engine infrastructure.
它搭载在 Django 现有的模板引擎基础架构上。 A management command called
render_static
should be run before collectstatic
.一个名为
render_static
的管理命令应该在collectstatic
之前运行。 This command will look for templates registered in settings (or passed as arguments) and render them to your static file location on disk.此命令将查找在设置中注册(或作为参数传递)的模板,并将它们呈现到磁盘上的静态文件位置。 They're then available for whatever normal static file packaging pipeline you have configured.
然后它们可用于您配置的任何普通静态文件打包管道。
I'm sure there are more use cases, but the two most common I've found are providing a reverse
utility in static JavaScript thats equivalent to Django's and auto-translating define-like python structures (ie choice fields) into JavaScript.我确信还有更多的用例,但我发现的两个最常见的是在静态 JavaScript 中提供一个
reverse
实用程序,相当于 Django 的和自动翻译类似定义的 python 结构(即选择字段)到 JavaScript。 The app provides template tags that do both.该应用程序提供了两者兼具的模板标签。
The JavaScript url reversal code is guaranteed to be functionally equivalent to Django's reverse
function. JavaScript url 反转代码保证在功能上等同于 Django 的
reverse
功能。 I won't bother plopping example code down here because it's been well documented .我不会费心把示例代码放在这里,因为它已经被很好地记录了下来。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.