Django对静态文件的处理——部署阶段

Django 的官方文档中说,Django 主要关注的是 Web App 的动态部分,像图片、CSS、JS 等的静态文件都应该交由专门的服务器来处理。

但在开发阶段,本地不一定能模拟生产环境,这时也是要使用静态文件的。为此 Django 提供了一些工具来处理静态文件,作为开发阶段的临时解决方案。

所以就分 开发阶段 和 部署阶段 两种情况来说 Django 的静态文件处理。

部署阶段

这个比较简单,因为 Django 将这部分的工作完全抛给服务器(比如 Nginx)了:在 HTML 中指定 URL,同时将要用到的静态文件都放在一个地方,然后告诉服务器当对这些 URL 发起请求时到这个地方去寻找。

Django 在这个阶段的工作中只是提供了几个辅助工具。

    • django.contrib.staticfiles,用来将该 Django 项目用到的所有静态文件统一收集到一个单独的文件夹中,这样在服务器配置中指向这个文件夹即可。主要操作如下:

      • 到 settings.py 中设置 STATICFILES_DIRS(可以不设置),告诉 staticfiles 去哪儿找静态文件。同时,staticfiles 默认都会搜集每个应用目录下的 static/ 文件夹。

      • 到 settings.py 中设置 STATIC_ROOT ,告诉 staticfiles 将所有的静态文件收集到哪里。

      • 确保 INSTALLED_APPS 中有 django.contrib.staticfiles 这项。

      • 运行如下命令后,所有的静态文件就会被拷贝到 STATIC_ROOT 目录下。

        1
        ./manage.py collectstatic

当然了,你完全可以不用管这些,手动将你要用到的静态文件收集到一起,如果你的项目很小的话。staticfiles 只是一个可选工具,其本身也是在 1.3 之后才引入 Django 中,它的前身是 Django 的第三方工具包 django-staticfiles

    • static 模板标签,用来生成静态文件的 URL 地址。这样当负责静态文件的服务器发生变动的时候,就不用一个个地改模板了。有以下几种方式:

      • 直接在模板中使用 STATIC_URL 变量,比如

        1
        <img src="{{ STATIC_URL }}images/hi.jpg" />

        当然这个变量不是凭空来的,它是 django.core.context_processors.static 提供的,默认已经在 TEMPLATE_CONTEXT_PROCESSORS 中开启了。因为用到了 context_processor,所以你需要在渲染模板的时候使用RequestContext ,如果你用的是 render_to_response,那么就是:

        1
        2
        return render_to_response("some.html", {},
                context_instance=RequestContext(request))
      • 如果嫌 RequestContext 麻烦,你可以使用 get_static_prefix 这个内置的模板标签,效果是一样的:

        1
        2
        {% load static %}
        <img src="{% get_static_prefix %}images/hi.jpg" />
      • 你也可以用另外一个内置模板标签 static,同样不需要 RequestContext:

        1
        2
        {% load static %}
        <img src="{% static "images/hi.jpg" %}" />

        它实际上调用的是 Python 内置模块中的 urlparse.urljoin(),将 STATIC_URL 和 后面的 path 拼接到了一起。

      • 还有一个同名但更强大的 static 模板标签,存在于之前提到过的 staticfiles 组件中,用法类似:

        1
        2
        {% load staticfiles %}
        <img src="{% static "images/hi.jpg" %}" />

        注意 load 的对象不同。这个 static 的强大之处在于,即使你更换了静态文件的存储方式(比如使用了 CDN 或者某种云服务),仍然不用修改模板。你只需要更改 STATICFILES_STORAGE 中使用的存储引擎即可,通过修改存储引擎中的对应方法来改变 static 标签的行为。

这几个方法看起来让人眼花缭乱,实际使用中不用纠结这么多,Django官方建议直接使用 staticfiles 中的 static,以方便以后的扩展。而前三种方法,大概可以看做历史遗留产物了吧。

这就是 Django 为部署阶段提供的两方面帮助:收集静态文件,生成静态资源的 URL。

下面来总结下上面提到过的 settings.py 中的设置项:

  • STATIC_ROOT:执行 ./manage.py collectstatic 后,所有静态文件就会被收集到这个文件夹下;

  • STATIC_URL:静态文件的 URL 前缀,供类似 static,get_static_prefix 等模板标签使用;

  • STATICFILES_DIRS:除 每个应用目录下的 static/ 目录外,其他静态文件可能存放的目录;

  • STATICFILES_FINDERS:告诉 collectstatic 命令都需要去哪儿找静态文件,以及寻找的顺序,有点儿类似 TEMPLATE_LOADERS;

  • STATICFILES_STORAGE:collectstatic 命令所使用的存储引擎,默认情况下不用修改,使用内置的 StaticFilesStorage 即可。如果要使用 CDN 或云服务来提供静态资源,可以编写相应的存储引擎并替换即可。

  • INSTALLED_APPS:要使用上面这些功能,就要在这里开启 django.contrib.staticfiles 这个应用;另外,只有在这里出现的应用才会被 collectstatic 搜集到。

还有两个相关的设置项:

  • MEDIA_ROOT:用来存放用户上传文件的目录。

  • MEDIA_URL:用户上传文件的 URL 前缀。

在之前版本的 Django 中,不区分 MEDIA_ROOT 和 STATIC_ROOT,显然不太合适。分开之后,你可以将 MEDIA_ROOT 中的文件像其他静态文件一样,交给专门的服务器处理,或者使用 CDN 和云服务资源。staticfiles 这个工具并不干涉 MEDIA_ROOT 中的文件。用户上传文件在 Django 看来属于 Stored Files,区别于 Static Files 来看待,这就是另外一个话题了。

posted @ 2015-02-26 14:03  郑文亮  阅读(848)  评论(0编辑  收藏  举报