静态文件如何管理

网站通常需要提供对一些图片、js脚本、CSS文件的访问。在django里,我们把这些文件叫做“静态文件”。django提供了django.contrib.staticfiles这个app来帮助你管理静态文件。

以下将描述你可以如何提供这些静态文件的访问。

配置静态文件

  1. 确保django.contrib.staticfiles在settings.py的INSTALLED_APPS里已经启用。

  2. 在settings.py中,定义STATIC_URL配置项,例如:

    STATIC_URL = '/static/'
  3. 在模板中,使用static模板标签来构建由静态文件的相对路径和 STATICFILES_STORAGE(即静态文件所处的服务器地址)

    形成的URL。

    {% load static %}
    <img src="{% static "my_app/example.jpg" %}" alt="My image"/>
  4. 将你的静态文件放置于你的app下叫做static的目录下。比如:my_app/static/my_app/example.jpg

静态文件如何可以正常访问

配置完成后,你还需要实际为这些文件提供访问支持。

在开发过程中,如果你使用了django.contrib.staticfiles这个app,且DEBUG被设置为True,这个任务将由runserver功能自动完成(详见django.contrib.staticfiles.views.serve())。

但这种方式是非常低效甚至不安全的,所以不适合在生产环境应用。

所以请参考Deploying static files ,得知如何为静态文件提供正式访问服务。

你的项目可能会有不仅适用于某一个app的静态文件。除了使用你app里的static目录,你可以在settings.py额外定义一系列目录,django将在这些目录里寻找静态文件。比如:

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),
    '/var/www/static/',
]

关于staticfiles如何查找你的静态文件,查看这里看详细内容: STATICFILES_FINDERS

通过STATICFILES_DIRS的配置,我们可以实现直接把静态文件全部放在my_app/static/中,而不用再创建一个app名称的子目录。但是实际上这样做并不好。django在寻找静态文件时,会匹配遇到的第一个名字正确的文件,如果你在不同的app内有重名的静态文件,django就无法区分它们。这种情况下就必须建立app名称目录,使静态文件与app对应起来。

开发过程中提供静态文件访问(同样可用于上传文件的访问)

正如上面说到的,如果你使用了django.contrib.staticfiles,runserver将自动完成这项任务(DEBUG需要设为TRUE)。如果你在INSTALLED_APPS中没启用django.contrib.staticfiles,你可以手动使用django.views.static.serve() 这个view来提供访问服务。例如,你的STATIC_URL定义为/static/,你可以在urls.py中添加如下代码实现静态文件访问:

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # ... the rest of your URLconf goes here ...
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

注意:

static助手函数只能在debug模式使用,并且只能接受本地路径为参数,如果参数为url则不生效。同时,它只能为STATIC_ROOT文件夹提供访问支持,无法像django.contrib.staticfiles一样提供静态文件自动查找功能。

部署

django.contrib.staticfiles提供了方便的命令供开发者将静态文件收集到一个目录里,以便于方便地统一提供访问支持。

  1. 设置STATIC_ROOT,告诉django静态文件最终的位置

    STATIC_ROOT = "/var/www/example.com/static/"
  2. python manage.py collectstatic该命令将把你所有静态文件目录内的文件复制到上面的路径里。

  3. 在web服务器里对以上路径提供访问支持即可。

部署静态文件

生产环境部署静态文件的整体思想是很简单明了的:当静态文件有变化时,用collectstatic命令收集它们,然后对收集完成的目录内文件提供访问支持。根据STATICFILES_STORAGE的配置,它们可能需要手动放到别的地方存储,也可能通过Storage类的post_process方法处理它们。

以下为几种常用的提供访问的策略

与站点一起部署

直接配置Apache或nginx,将对STATIC__URL的访问解析到STATIC__ROOT目录内

专门的server

依然是配置Apache或nginx,文件部署可以使用rsync

云服务或CDN

可以通过设置STATICFILES_STORAGE告诉collectstatic将静态文件收集到哪里。例如

STATICFILES_STORAGE = 'myproject.storage.S3Storage'

settings说明

STATIC_ROOT

默认值:None

在部署上线时运行python manage.py collectstatic 命令收集静态文件后的存放目录

例如:"/var/www/example.com/static/"

如果staticfilesapp被启用,collectstatic管理命令将把静态文件收集到这个目录里。详见管理静态文件

STATIC__URL

默认值:None

访问STATIC__ROOT目录内静态文件时的URL

例如可以是"/static/","http://static.example.com/"

该值非空时,将被用于asset definitionsstaticfiles app的基本目录

参数最后必须以/结尾。

STATICFILES_DIRS

静态文件的额外寻找目录(绝对路径列表),windows下也用/

STATICFILES_DIRS = [
    "/home/special.polls.com/polls/static",
    "/home/polls.com/polls/static",
    "/opt/webfiles/common",
]

可选前缀作为命名空间

STATICFILES_DIRS = [
    # ...
    ("downloads", "/opt/webfiles/stats"),
]

此设置下,collectstatic在把/opt/webfiles/stats下的静态文件复制到STATIC__ROOT里时,会创建一个downloads文件夹。此时:

绝对路径:
'/opt/webfiles/stats/polls_20101022.tar.gz'
url:
'/static/downloads/polls_20101022.tar.gz'
模板引用
<a href="{% static "downloads/polls_20101022.tar.gz" %}">

STATICFILES_STORAGE

STATICFILES_FINDERS