解决uWSGI里的Django静态文件丢失
用uWSGI来单独运行一个Django应用,有一个static文件丢失的大坑。 本文介绍如何出坑。
(本文针对的Django版本在1.4以上,因为1.3以前有ADMIN_MEDIA_PREFIX这个坑,本文并不涉及。)
问题
一个Django应用,在./manage.py runserver
情况下,正常运行。 而在uWSGI运行的情况下,则网页样式奇怪,静态文件找不到。
也就是说,调试的情况下没问题,生产环境找不到静态文件。
(假如在runserver
的调试环境下也有问题,则通常是配置有误。 本文不讨论配置错误的情况。)
以下举例说明。
在settings.py
配置中,使用了django.contrib.staticfiles
,并且做出以下配置。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
BASE_DIR = os.path.dirname(os.path.realpath(__file__)) STATIC_ROOT = '/srv/django/static' STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static'), )
现象为,STATIC_URL
位置的文件,在uWSGI下,无法用浏览器访问,而在runserver
下则没问题。
原因
一个Django应用,一般有两类静态文件。 一是应用内的静态文件,二是Django自带的。
按照前面代码的示例,应用内的静态文件在与settings.py
同级的static
目录下。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static'), )
此外,在INSTALLED_APPS
中配置了django.contrib.admin
, 则还会有另外一组静态文件,在Django安装位置里。
例如,一个root在Python 3.6版本安装的Django,admin的静态文件在: /usr/local/lib/python3.6/site-packages/django/contrib/admin/static/admin/
。
最终,在STATIC_URL
里,会有两类静态文件。 /static/*
与/static/admin/*
。
了解原理,原因就很显然了。 uWSGI根本不知道静态文件在什么位置。
解决
STATIC_ROOT
这个参数,在runserver
情况下是无用的,因为Django自己知道位置在哪。
在集成了django.contrib.staticfiles
后,./manage.py
多了一个子命令。
./manage.py collectstatic
这个子命令,会把所有STATICFILES_DIRS
目录下的文件,都复制到STATIC_ROOT
中。 在这里,也就是/srv/django/static
目录下。
uWSGI也是支持静态文件的,可以通过执行时添加参数:
uwsgi --static-map /static=/srv/django/static
或者,在配置文件中添加:
static-map = /static=/srv/django/static
=
前面的/static
是uWSGI的URL前缀,而后面的/srv/django/static
则是静态文件的路径。 这个路径,通常使用绝对路径,但也支持相对路径。
所以,生产环境部署时,解决方案一共分两步:
- 使用
collectstatic
子命令,收集、复制相关静态文件。 - 启动uWSGI,其中包含
static-map
配置、或--static-map
参数。
另外,如果是使用Nginx代理,也可以考虑把静态文件交给它。 这里不做介绍。