1. 程式人生 > >Django關於訪問靜態檔案總結

Django關於訪問靜態檔案總結

簡介

開發網站的過程中,我們需要使用到大量的靜態檔案,例如jsCSS,圖片等等,一般我們會在網頁中以URL的形式引用它們。Django提供了一些特殊的機制來處理靜態檔案。預設情況下(如果沒有修改STATICFILES_FINDERS的話),Django首先會在STATICFILES_DIRS配置的資料夾中尋找靜態檔案,然後再從每個appstatic子目錄下查詢,並且返回找到的第一個檔案。所以我們可以將全域性的靜態檔案放在STATICFILES_DIRS配置的目錄中,將app獨有的靜態檔案放在appstatic子目錄中。存放的時候按類別存放在static目錄的子目錄下,如圖片都放在images

資料夾中,所有的CSS都放在css資料夾中,所有的js檔案都放在js資料夾中。

配置全域性的靜態檔案目錄

預設情況下,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目錄,將檔案直接放進去就可以了。如果DjangoSTATICFILES_DIRS當中沒有找到的話,會到app的目錄下的static目錄去查詢的。

使用

假設我們在STATICFILES_DIRS配置的目錄中,放了一個Chrome.jpg圖片檔案,在網頁中可以通過/static/Chrome.jpg來引用。當然這是預設情況,

/static/這個字首可以通過配置檔案中的STATIC_URL來修改。

另外,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'>