用uWSGI來單獨運行一個Django應用,有一個static文件丟失的大坑。 本文介紹如何出坑。
(本文針對的Django版本在1.4以上,因為1.3以前有ADMIN_MEDIA_PREFIX這個坑,本文並不涉及。)
問題
一個Django應用,在./manage.py runserver
情況下,正常運行。 而在uWSGI運行的情況下,則網頁樣式奇怪,靜態文件找不到。
也就是說,調試的情況下沒問題,生產環境找不到靜態文件。
(假如在runserver
的調試環境下也有問題,則通常是配置有誤。 本文不討論配置錯誤的情況。)
以下舉例說明。
在settings.py
配置中,使用了django.contrib.staticfiles
,並且做出以下配置。

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
目錄下。

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代理,也可以考慮把靜態文件交給它。 這里不做介紹。