首先,不管常识也好,django自己的文档也罢,用应用服务器发送静态资源文件一直就不是什么好办法,尤其用python、java这种东西做的应用服务器,几乎没什么可能达到apache、lighttpdcherokeenginx之流的性能——当然有人说nginx是web应用平台,换而言之,应用服务器,这个我也没话说。

有关配置django通过runserver方式启动的开发测试用服务器处理用来发送静态文件的文档在:http://docs.djangoproject.com/en/1.2/howto/static-files/ ,也是警告了无数次这样做不好,只限于开发目的。

近来和几个同学做个练手的小东西,基本上就我还算知道一些web方面的事儿,大伙都是传统软件开发行业出身,nginx这种看起来很geeky的东西,八成下意识都觉得离远点儿好(这也是当初为啥我看了一阵子cherokee,毕竟管理UI太Q太省心了…),所以和哥儿几个白话了会儿选型,就有人问,诶,能让django直接管HTTP服务嘛?想想也可以理解,nginx那东西,win下还不知道啥德行了,反正我没碰过,出什么问题真耽误人家时间啊。遂折腾了一下,照文档配的,也很简单,可最后静态资源怎么都是找不到,怎么看配置都没问题的啊…

后来问题解决了,其实可能也就是个比较不常见的配置问题,原因是我把admin和site的media目录配成同一个了…当初就是觉得一是省事,二是看了看admin里的js和css,有一些东西很有重用的价值。没想到给后来埋下这么个麻烦。

怎么改配置文件都没法解决问题,直接看代码吧。

调用流程是:
[sourcecode language=’python’]manage.py -> django.core.management.execute_manager()
-> django.core.management.ManagementUtility.execute()
-> django.core.management.commands.runserver.Command.handle()
-> django.core.servers.basehttp.run()
-> django.core.servers.basehttp.WSGIRequestHandler.handle()
-> django.core.servers.basehttp.ServerHandler.run()
-> django.core.servers.basehttp.AdminMediaHandler.()[/sourcecode]
让我最开始很迷惑的就是runserver.Command里面直接诡异地传了AdminMediaHandler去后续处理请求,刚开始看代码的时候总觉得是不是哪里看错了,让个这么霸道的名字唬住了。后来一通traceback.print_stack()才敢确信,配好的django.views.static.serve()根本就没调到。

因为,AdminMediaHandler()中有这么一段判断:
[sourcecode language=’python’]if self.media_url.startswith(‘http://’) or self.media_url.startswith(‘https://’) \
or not environ[‘PATH_INFO’].startswith(self.media_url):
return self.application(environ, start_response)[/sourcecode]
因为配置里的ADMIN_MEDIA_PREFIX和MEDIA_URL都是/media/,就会导致这个条件判断为False无法进到application(),which会辗转进入后面的django.views.static.serve(),而是在admin应用的media里寻找文件,最后因为找不到返回HTTP 404。

解决方法嘛,也没啥太好的方法,不值得因为这么个破事儿去hack配置文件,把开发环境和部署环境搞的差异很大,所以就把admin用到的静态文件挪了挪窝 😀

至于为啥要打开admin嘛…我就是觉得admin挺好玩的…