Django应用如何打包静态资源?
背景:
我第一次使用Django,这也是我第一次接触网页开发。我在“提供静态媒体”这个问题上卡住了。花了一段时间看文档和StackOverflow上的问题后,我觉得我明白了它应该怎么运作(比如说,MEDIA_ROOT、MEDIA_URL、更新urls文件等等)。
我的问题:
好吧,我不太确定的部分是,Django应用应该是“可插拔”的,也就是说,我可以把一个应用从一个项目移动到另一个项目。那么,这些应用应该如何打包静态媒体呢?
举个例子,假设我有一个“foo”应用,它有一些模板需要加载css或图片文件。我应该把这些文件放在哪里,以便在我包含这个应用时,它们能自动被提供出来?
我看到的唯一解决方案是,安装一个应用时必须额外复制它的静态媒体到你自己服务器上的某个地方,以便提供这些媒体。
这是被接受的做法吗?虽然多了一步,但也许在网页开发中这是标准流程(我还是新手,所以不太清楚)。
另外,如果这是正确的做法,有没有标准的方法来收集我所有的静态媒体,以便我能清楚知道需要提供哪些?(比如说,应用里是否标准有一个叫“media”的文件夹?)
谢谢,
3 个回答
我通常把应用程序的媒体文件放在 ./apps/appname/static 这个文件夹里(我的应用程序都在一个名为 apps 的子文件夹里)。
然后在 Apache 的虚拟主机配置中,我会有类似这样的设置:
AliasMatch ^/apps/([^/]+)/static/(.*) /home/django/projectname/apps/$1/static/$2
<DirectoryMatch "^/home/django/projectname/apps/([^/]+)/static/*">
Order deny,allow
Options -Indexes
deny from all
Options +FollowSymLinks
<FilesMatch "\.(flv|gif|jpg|jpeg|png|ico|swf|js|css|pdf|txt|htm|html|json)$">
allow from all
</FilesMatch>
</DirectoryMatch>
在我的 urls.py 文件中,我也有这样的配置,主要是为了开发服务器(仅用于调试):
def statics_wrapper(request, **dict):
from django.views import static
return static.serve(request, dict['path'], document_root = os.path.join(settings.BASE_DIR, 'apps', dict['app'], 'static'), show_indexes=True)
urlpatterns += patterns('', (r'^apps/(?P<app>[^/]+)/static/(?P<path>.+)$', statics_wrapper))
这样做非常方便,因为静态文件的 URL 直接映射到文件系统上,比如:
http://wwww.ecample.com/apps/calendar/static/js/calendar.js 这个链接对应的文件实际上就在 [BASE_DIR]/apps/calendar/static/js/calendar.js 这个位置。
希望这对你有帮助。
我知道的唯一一个可以在不干预的情况下处理这个问题的应用是非常棒的 django-debug-toolbar,不过有人可能会说这不是个好例子,因为它是专门为调试模式设计的应用。
它处理这个问题的方式是通过Django本身来提供它的媒体文件——你可以查看 urls.py 的源代码:
url(r'^%s/m/(.*)$' % _PREFIX, 'debug_toolbar.views.debug_media'),
一般来说,这种做法并不好(你不想通过Django来提供静态文件),根据 文档中的这条评论:
[通过Django提供静态文件]效率低下且不安全。不要在生产环境中使用这个。只在开发中使用。
显然,django-debug-toolbar只在开发中使用,所以我觉得它的部署方式是合理的,但这确实是个例外。
通常,我知道的最好方法是创建符号链接,把你的媒体文件存放在应用代码里的媒体文件夹中。例如,在你的应用里创建一个叫 media
的文件夹,然后要求安装你应用的用户要么从他们的媒体目录添加一个符号链接,要么复制整个文件夹。
一般来说,静态文件会放在应用的 media/appname/ 或者 static/appname/ 目录下,这和模板的放置方式类似。
如果你在项目中使用带有静态文件的应用,我强烈推荐使用 django-staticfiles。这个工具会在开发时自动处理静态文件(包括应用中的静态文件),通过一个视图来替代 django.views.static.serve,并且它还提供了一个叫做 build_static 的管理命令,可以把所有应用的静态文件复制到一个单独的目录中,以便在生产环境中使用。
更新:django-staticfiles 已经 成为 Django 1.3 的一部分。现在它要求应用的静态文件放在应用的 "static/" 子目录下,而不是 "media/"。而且管理命令现在叫做 "collectstatic"。