Django關於訪問靜態檔案總結
簡介
開發網站的過程中,我們需要使用到大量的靜態檔案,例如js,CSS,圖片等等,一般我們會在網頁中以URL的形式引用它們。Django提供了一些特殊的機制來處理靜態檔案。預設情況下(如果沒有修改STATICFILES_FINDERS的話),Django首先會在STATICFILES_DIRS配置的資料夾中尋找靜態檔案,然後再從每個app的static子目錄下查詢,並且返回找到的第一個檔案。所以我們可以將全域性的靜態檔案放在STATICFILES_DIRS配置的目錄中,將app獨有的靜態檔案放在app的static子目錄中。存放的時候按類別存放在static目錄的子目錄下,如圖片都放在images
配置全域性的靜態檔案目錄
預設情況下,STATICFILES_DIRS為空,我們可以這樣配置:
import os.path
STATICFILES_DIRS = (
# Put strings here, like "/home/html/static" or "C:/www/django/static".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
os.path.join(os.path.dirname(__file__), 'static').replace('\\','/'),
)
然後手動建立static資料夾,效果如圖:
配置app的靜態檔案目錄
直接在每個app目錄下建立static目錄,將檔案直接放進去就可以了。如果Django在STATICFILES_DIRS當中沒有找到的話,會到app的目錄下的static目錄去查詢的。
使用
假設我們在STATICFILES_DIRS配置的目錄中,放了一個Chrome.jpg圖片檔案,在網頁中可以通過/static/Chrome.jpg來引用。當然這是預設情況,
另外,Django提供了一個findstatic命令來查詢指定的靜態檔案所在的目錄,例如:D:\TestDjango>python manage.py findstatic Chrome.jpg
('D:/TestDjango/TestDjango/templates',)
Found 'Chrome.jpg' here:
D:\TestDjango\TestDjango\static\Chrome.jpg
注意事項
以上是開發過程中關於靜態檔案的配置,注意是開發階段而不是部署階段。注意到關於靜態檔案還有一個配置變數STATIC_ROOT,這是幹嘛的呢?當工程部署之後,處理靜態檔案較好的方法是交給Web容器來做,比如Apache,所以我們要將所有的靜態檔案放在一起,然後交給Apache託管,Django提供了一個命令collectstatic用來把所有的靜態檔案收集到STATIC_ROOT當中。所以有一個問題就是,所有的靜態檔案,最好不要有重名,筆者尚不瞭解重名會有什麼結果。
1、Django settings中關於靜態檔案的配置
Django 1.3以後,採用static方式處理靜態檔案,比如網站的css js images等等,而以前所謂的media改成處理網站自身以外的媒體檔案了。media和static用途上容易混淆,請移步上次講的《對Django media和static概念的理解》。
如果簡單使用static,配置起來會比media要少一步,下面會比較一下。說到static,不能不說說Django開發環境和部署環境的區別,Django配置檔案settings.py裡的DEBUG變數就是主要的區別, DEBUG=True,說明是在開發環境(除錯模式)下,DEBUG=False反之是在正式部署環境下使用。兩者有很大的區別,比如快取,出錯資訊的方式等等,還有今天說的靜態檔案的處理方式上。開發環境下靜態檔案都是通過Django自帶的web伺服器來處理的(這樣會更方面)。如果把DEBUG設定成False,那麼Django自帶的web伺服器自然不處理靜態檔案了,靜態檔案都交給nginx,apache來處理吧(這樣會更高效)。
具體說說static在開發環境下怎麼配置吧。
這次主要拿Django 1.4版本來做配置,這個要事先宣告,因為1.4以後,Django的專案結構發生很大的變化,如果下面的配置做法放到Django 1.3上肯定不適應了,值得注意哦。staitc的配置只要在settings.py裡做即可。
DEBUG=True
這個設定環境是處在開發環境下。
然後自己建立一個變數SITE_ROOT,變數不是必須的,只是為了方面重用,名字可以隨意起。
import os
SITE_ROOT=os.path.join(os.path.abspath(os.path.dirname(__file__)),'..')
變數值專案的根目錄,也就是settings.py的存放位置。
然後給靜態檔案變數賦值,告訴Django,靜態檔案在哪裡【靜態檔案變數是系統定義好的,給系統用】
STATIC_ROOT = os.path.join(SITE_ROOT,'static')
說到這裡,我還是說說專案檔案結構吧,這個容易蒙人,比如這次的講的專案結構如下:
myproject
----myproject
--------__init__.py
--------settings.py
--------urls.py
--------wsgi.py
----blog
--------__init__.py
--------models.py
--------views.py
--------test.py
----static
--------css
------------style.css
--------js
------------jquery.js
--------images
------------me.jpg
----media
--------upload
注意專案的結構,你會發現SITE_ROOT就是
myproject
----myproject
的路徑。
STATIC_ROOT就是
myproject
----media
的路徑。
好,接著配置說
STATIC_URL = '/static/' 【為了生成系統預設寫的url的第一個引數'^/static'】
上句意思是給靜態檔案url(即STATIC_URL)一個字尾,在templates裡用到的。
【注:STATIC_URL和後面的STATICFILES_DIRS都是全域性的變數,模板裡可以直接用】
最後關鍵的部分是STATICFILES_DIRS以下配置
STATICFILES_DIRS = (
("css", os.path.join(STATIC_ROOT,'css')),
("js", os.path.join(STATIC_ROOT,'js')),
("images", os.path.join(STATIC_ROOT,'images')),
) 【為了生成系統預設寫的url的第三個引數'e:/xxx/xxx'】
簡要說一下,static資料夾在專案裡,有css js images 三個資料夾(看專案結構),他們的路徑分別是:
os.path.join(STATIC_ROOT,'css'),os.path.join(STATIC_ROOT,'js'),os.path.join(STATIC_ROOT,'images');
我們分別給他們起三個別名css,js,images(你可以隨意給,不過為了易記,我們原名稱指定別名了)
到這裡staitc算是配置完成了,並不需要再urls.py裡配置相關的東西,Django就會自動找到對的路徑解析靜態檔案了,也是在配置上static比media少了一步。 【估計是django根據上面的STATIC_URL和STATICFILES_DIRS自動生成了一些url('^/static/' ,fun, 'path':'e:/xxx/xxx')】
配置好了,在templates 就能正常使用靜態檔案了。怎麼用?拿一個templates講解吧。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset=utf-8>
<title>staitc例子</title>
<link rel="stylesheet" type="text/css" href="{{STATIC_URL}}css/style.css" media="screen" /> 【或直接寫成:/static/css/style.css】
<script type="text/javascript" src="{{STATIC_URL}}js/jquery.js"></script>
</head>
<body>
<img src="{{STATIC_URL}}images/me.jpg"" alt="img">
</body>
</html>
注意{{STATIC_URL}}就是取配置檔案settings.py裡的STATIC_URL變數,解析出來的就是:/static/。
而{{STATIC_URL}}css/style.css最終解析出來的就是我們想要的:/static/css/style.css,Django會根據配置檔案找到相應的檔案。
【上面的:/static/css/style.css在訪問時自動解析/static為網站全名路徑】
快到尾聲的時候,講講正式部署環境怎麼設定吧:
DEBUG=False
首先把DEBUG設定為False,告訴Django環境是正式的非除錯模式下了,然後Django就不再通過自己來處理靜態頁面了,最後靜態檔案都交給Nginx Apache來處理了。
說說Nginx怎麼配置,才能正確解析靜態檔案吧,在一個server裡新增一個location靜態檔案處理
location /static/ {
root /home/www-data/twogoo/myproject/;
}
這個也有一個容易犯錯的地方,就是路徑,有的同學常常指定這樣的路徑:/home/www-data/twogoo/myproject/staitc/;這樣Nginx應該找不到靜態檔案的,因為Nginx會跑到/home/www-data/twogoo/myproject/staitc/staitc/路徑裡找,注意這點,靜態檔案處理上你會順很多。
2、django css樣式,圖片路徑問題解決方案
在用Django 做專案時,如果在本地除錯的情況下,我們會開啟 settings.py 中的 DEBUG = True
同時我們還會做如下操作:
1. 設定 STATIC_ROOT = os.path.join(os.path.dirname(__file__),'static') 【定義這個變數就是為了給STATICFILES_DIRS用,能少寫些程式碼。其他情況基本不用】
2.設定 STATIC_URL = '/static/'
以上兩步我想一般都會提到,但即使你做了這樣的配置,當你在瀏覽器中瀏覽你的CSS或JS 檔案,仍然是 404 錯誤,說明路徑錯誤,根本找不到。
比如我的工程如下:
STATICFILES_DIRS = (
('css',os.path.join(STATIC_ROOT,'css').replace('\\','/') ),
('js',os.path.join(STATIC_ROOT,'js').replace('\\','/') ),
('images',os.path.join(STATIC_ROOT,'images').replace('\\','/') ),
('upload',os.path.join(STATIC_ROOT,'upload').replace('\\','/') ),
)
注意前面的css,js,images,upload
一定要與你的目錄結構名稱保持一致。
配置好了你再次啟動django ,然後訪問:http://localhost:8000/static/js/myjs.js就看到結果了,說明找到路徑,同樣css,image圖片都可以找到了.
在模板中的使用
<script type="text/javascript" src="/static/js/myjs.js"></script>
採用這種方式就可以了。css與圖片同樣的道理。
注意在上訴情況下,只能在開啟 DEBUG=True 時才能生效,在我們開發的時候很方便。如果設定DEBUG=False 將不會生效。這種情況時,要採用生產環境的 配置。用web application server 來處理這些靜態的圖片,css,以及js檔案。
生產環境的處理
1.設定 DEBUG=False
2.可以不用配置STATICFILES_DIRS
3.配置web application server ,比如我用 nginx:
location ^~ /static {
root /opt/www/MyNet;
}
這樣,就自然找到static路徑,不用 django去處理了。如果想配置生產環境的,可以參考我寫的另一篇文章:生產環境上配置django
備註:我看到有的文章在urls.py 中進行配置,確實可以,但我覺得這不是個好方法。比如:
MEDIA_ROOT=os.path.join(os.path.dirname(__file__),'media').replace('\\','/') #如果是*nix系統,不需要replace函式
MEDIA_URL='/media/' #末尾一定要加上/
ADMIN_MEDIA_PREFIX = '/media/admin/' #填啥都可以,就是不能跟MEDIA_URL一樣
然後
(r'^media/(?P.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT})
3、django1.4設定模板路徑和CSS,JS,image等路徑的方法
對於DJANGO這類MVC框架來說,路徑問題可以稱為一個謎一樣的東西,很多人因為對路徑不知道如何處理而覺得MVC實在是雲裡霧裡不知所云。
本文主要解決django中關於模板路徑設定、CSS檔案路徑設定、JS檔案路徑設定、圖片路徑設定等常見問題。文中將templates和media(包含js、css、images目錄)放到了專案目錄的根目錄,更具有一般性質。
設定模板路徑
設定模板路徑比較簡單,只要在setting.py裡面的TEMPLATE_DIRS選項裡面加上這麼一句話即可:
1 2 3 4 5 | importos.path TEMPLATE_DIRS=( os.path.join(os.path.dirname(__file__),'../templates').replace('\\','/'), ) |
這意味著,你可以在專案的根目錄下面,建立一個templates目錄,裡面放你所有的模板
設定CSS/JS/IMAGES等路徑
1、在setting.py裡面,加入下面一句話,指定根目錄下面的media路徑:
1 | STATIC_PATH=os.path.join(os.path.dirname(__file__),'../media').replace('\\','/') |
2、在urls.py裡面設定這麼一句話,將請求CSS/JS/IMAGES的URL轉到該地方
1 | (r'^site_media/(?P<path>.*)$','django.views.static.serve',{'document_root':settings.STATIC_PATH}), |
3、那麼在我們的模板裡面,現在已經可以用以下方法訪問JS/CSS/IMAGES
1 | <linkhref="/site_media/style/style.css"rel="stylesheet"type="text/css"/> |
該方法的一個優點是,不用詳細設定JS、CSS、images三個不同的路徑,只要設定一個,在模版檔案裡面,直接指定檔案的子目錄就可以了,比如圖片和JS可以這麼寫:
<img src=’/site_media/images/a.jpg’>
<script src=’/site_media/js/s.js’> </script>
請看這裡,我們並沒有在urls.py中指定/site_media/images這樣的路徑。
4、和3類似,django 中式用靜態檔案(css,javascript)
測試環境
(r'^css/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/var/www/django-demo/css'}), 【這種方式相當於不採用系統預設生成的url了,自己寫了】
(r'^js/(?P</path><path>.*)$', 'django.views.static.serve', {'document_root': '/var/www/django-demo/js'}),
(r'^images/(?P</path><path>.*)$', 'django.views.static.serve', {'document_root': '/var/www/django-demo/images'}),
模板中使用下述方式即可:
<link href="/css/demo.css" type="text/css" rel="stylesheet">
注:可採用os.path.dirname(globals()["__file__"])來獲得當前檔案所在路徑,比如
(r'^css/(?P<path>.*)$', 'django.views.static.serve', {'document_root': os.path.dirname(globals()["__file__"])+'/css'}),
可以使用os.path.abspath()函式返回此路徑的絕對路徑。
==============
要在django的tempalte file中引用css、js、gif等靜態檔案,首先一條setting.py中DEBUG開關開啟。
1、在project目錄下建立一個存放靜態檔案的目錄,如:medias
2、在url.py patterns中增加一行:
(r'^site_media/(?P<path>.*)$','django.views.static.serve',{'document_root':settings.STATIC_PATH}),
還要from django.conf import setting
3、在setting.py中加入一行:
STATIC_PATH='./medias'
如此設定後,就可以在template file 中引用media中存放的靜態檔案了,如:
<img src='/site_media/django.gif'>