静态文件

静态文件

一如其名,静态文件是那些不会改变的文件。一般情况下,在你的应用中,这包括 CSS 文件,Javascript 文件和图片。它也可以包括视频文件和其他可能的东西。

组织你的静态文件

我们将在应用的包中创建一个叫 static 的文件夹放置我们的静态文件。

  1. myapp/
  2. __init__.py
  3. static/
  4. templates/
  5. views/
  6. models.py
  7. run.py

static/ 里面的文件组织方式取决于个人的爱好。就我个人来说,如果第三方库(比如 jQuery, Bootstrap 等等)跟自己的 Javascript 和 CSS 文件混起来,我会因此而不爽。所以,我要将第三方库全放到一个 lib/ 文件夹中。有时会用 vendor/ 来代替 lib/

  1. static/
  2. css/
  3. lib/
  4. bootstrap.css
  5. style.css
  6. home.css
  7. admin.css
  8. js/
  9. lib/
  10. jquery.js
  11. home.js
  12. admin.js
  13. img/
  14. logo.svg
  15. favicon.ico

提供一个 favicon

用户将通过 yourapp.com/static/访问你的静态文件夹中的文件。默认下浏览器和其他软件认为你的 favicon 位于 yourapp.com/favicon.ico。要想解决这种不一致。你可以在站点模板的 <head> 部分添加下面内容。

  1. <link rel="shortcut icon" href="{{ url_for('static', filename='img/favicon.ico') }}">

用 Flask-Assets 管理静态文件

Flask-Assets 是一个管理静态文件的插件。它提供了两种非常有用的特性。首先,它允许你在 Python 代码中定义 多组(bundles)可以同时插入你的模板的静态文件。其次,它允许你预处理这些文件。这意味着你可以合并并压缩你的 CSS 和 Javascript 文件,这样用户就会仅仅得到两个压缩后的文件(CSS 和 Javascript)而免于花费太多带宽。你甚至可以从 Sass,Less,CoffeeScript 或别的源码里编译出最终产物。

下面是这一章中也做例子的静态文件夹的基本结构。

myapp/static/

  1. static/
  2. css/
  3. lib/
  4. reset.css
  5. common.css
  6. home.css
  7. admin.css
  8. js/
  9. lib/
  10. jquery-1.10.2.js
  11. Chart.js
  12. home.js
  13. admin.js
  14. img/
  15. logo.svg
  16. favicon.ico

定义分组

我们的应用有两部分:公共网站和管理面板(分别称作 “home” 和 “admin”)。我们将定义四个分组来覆盖它:每个部分有一个 Javascript 和一个 CSS 分组。我们将它们放入 util 包里的 assets 模块。

myapp/util/assets.py

  1. from flask_assets import Bundle, Environment
  2. from .. import app
  3. bundles = {
  4. 'home_js': Bundle(
  5. 'js/lib/jquery-1.10.2.js',
  6. 'js/home.js',
  7. output='gen/home.js),
  8. 'home_css': Bundle(
  9. 'css/lib/reset.css',
  10. 'css/common.css',
  11. 'css/home.css',
  12. output='gen/home.css),
  13. 'admin_js': Bundle(
  14. 'js/lib/jquery-1.10.2.js',
  15. 'js/lib/Chart.js',
  16. 'js/admin.js',
  17. output='gen/admin.js),
  18. 'admin_css': Bundle(
  19. 'css/lib/reset.css',
  20. 'css/common.css',
  21. 'css/admin.css',
  22. output='gen/admin.css)
  23. }
  24. assets = Environment(app)
  25. assets.register(bundles)

Flask-Assets 按照被列出来的顺序合并你的文件。如果 admin.js 依赖 jquery-1.10.2.js,确保 jquery 被列在前面。

我们通过字典来定义分组,这样方便注册它们。webassets,实际上是 Flask-Assets 的核心,提供了一系列方式来注册分组,包括上面我们演示的以字典作参数的方法。(译注:webassets 之于 Flask-Assets,正如 SQLAlchemy 之于 Flask-SQLAlchemy。)

参见 webassets在这里注册了分组: https://github.com/miracle2k/webassets/blob/0.8/src/webassets/env.py#L380

既然我们已经在 util.assets 中注册了我们的分组,剩下的就是在__init__.py 中,在 app 对象初始化之后,来导入这个模块。

myapp/__init__.py

  1. # [...] Initialize the app
  2. from .util import assets

使用你的分组

下面是我们的例子中的模板文件夹:

myapp/templates/

  1. templates/
  2. home/
  3. layout.html
  4. index.html
  5. about.html
  6. admin/
  7. layout.html
  8. dash.html
  9. stats.html

要使用我们的 admin 分组,我们将插入它们到 admin 部分的基础模板 - admin/layout.html - 中。

myapp/templates/admin/layout.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. {% assets "admin_js" %}
  5. <script type="text/javascript" src="{{ ASSET_URL }}"></script>
  6. {% endassets %}
  7. {% assets "admin_css" %}
  8. <link rel="stylesheet" href="{{ ASSET_URL }}" />
  9. {% endassets %}
  10. </head>
  11. <body>
  12. {% block body %}
  13. {% endblock %}
  14. </body>
  15. </html>

对于 home 分组,我们也同样在 templates/home/layout.html 做一样的处理。

使用过滤器

我们可以使用 webassets 过滤器来预处理我们的静态文件。这将方便我们压缩 Javascript 和 CSS 文件。现在修改下我们的代码来实现这一点。

myapp/util/assets.py

  1. # [...]
  2. bundles = {
  3. 'home_js': Bundle(
  4. 'lib/jquery-1.10.2.js',
  5. 'js/home.js',
  6. output='gen/home.js',
  7. filters='jsmin'),
  8. 'home_css': Bundle(
  9. 'lib/reset.css',
  10. 'css/common.css',
  11. 'css/home.css',
  12. output='gen/home.css',
  13. filters='cssmin'),
  14. 'admin_js': Bundle(
  15. 'lib/jquery-1.10.2.js',
  16. 'lib/Chart.js',
  17. 'js/admin.js',
  18. output='gen/admin.js',
  19. filters='jsmin'),
  20. 'admin_css': Bundle(
  21. 'lib/reset.css',
  22. 'css/common.css',
  23. 'css/admin.css',
  24. output='gen/admin.css',
  25. filters='cssmin')
  26. }
  27. # [...]

注意 要想使用jsmincssmin过滤器,你需要安装jsmin和cssmin包(使用pip install jsmin cssmin)。确保把它们也加入到requirements.txt

一旦模板已经渲染好,Flask-Assets 将在合并的同时压缩我们的文件,而且当其中一个源文件改变时,它会自动更新压缩文件。

注意 如果你在配置中设置ASSETS_DEBUG = True, Flask-Assets将独立输出每一个源文件而不会合并它们。

参见 你可以使用Flask-Assets过滤器来自动编译Sass,Less,CoffeeScript,和其他预处理器。来看下你还可以使用哪些过滤器: http://elsdoerfer.name/docs/webassets/builtin_filters.html#js-css-compilers

总结

  • 静态文件归于 static/文件夹。
  • 将第三方库跟你自己的静态文件隔离开来。
  • 在你的模板里指定你的 favicon 的路径。
  • 使用 Flask-Assets 将静态文件插入到你的模板中。
  • Flask-Assets 可以编译,合并以及压缩你的静态文件。