原文地址:[http://agiliq.com/blog/2013/03/serving-static-files-in-django/]css
處理靜態文件,尤爲是在開發時,是一件蛋疼的事情。在這篇文章中,咱們將會討論一些設置,目錄結構和他們之間的相互影響。設置好DEBUG = True
而後咱們開始開發吧。html
咱們將會建立一個Django項目,這樣可讓咱們更好的瞭解咱們討論的這些這些文件在什麼目錄中。咱們將會使用Django1.4,這些都也能在Django1.3中工做,由於沒有在Django1.2下進行測試,因此對1.2版本下是否有問題不是很清楚。python
若是你不須要這部分,能夠直接跳到處理靜態文件這一節。只要保證你看過了這節底部的目錄結構並對其有了解,這樣你閱讀後面的內容會更舒服。數據庫
咱們將在命名爲staticvirt的虛擬環境中作全部事情,因此咱們須要命令django
~$ virtualenv staticvirt
接下來咱們須要在這個虛擬環境中建立一個Django項目。確保你進入了虛擬環境的目錄,而且激活了該環境。同時也要保證在這個虛擬環境中安裝了Django,由於咱們不想污染系統的包環境。瀏覽器
~$ cd staticvirt/ ~/staticvirt$ source bin/activate (staticvirt)~/staticvirt$ pip install django==1.4
建立一個Django項目。bash
django-admin.py startproject test_project
進入項目所在系統。服務器
cd test_project/
讓咱們看看如今的目錄結構。app
(staticvirt)~/staticvirt/test_project$ tree . |-- manage.py *-- test_project |-- __init__.py |-- settings.py |-- urls.py *-- wsgi.py 1 directory, 5 files
如今查看下test_project/settings.py
的內容。搜索全部包括static的行,下面我列出全部包括static的行。測試
STATIC_ROOT = '' STATIC_URL = '/static/' STATICFILES_DIRS = () STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'django.contrib.staticfiles.finders.DefaultStorageFinder', ) INSTALLED_APPS = ( .... .... 'django.contrib.staticfiles', .... )
然而,這裏所看到的都是Django提供的默認設置,咱們沒有作任何的設置。
咱們建立一個app,咱們將會在裏面建立一個template,而後會寫一些靜態文件,好比樣式文件,而後在模板中使用這個樣式文件。
python manage.py startapp some_app
將some_app
添加進test_project/settings.py
中的INSTALLED_APPS
。
咱們須要一個urls.py
文件來爲some_app
定製路由。項目的urls.py應該包括some_app
中的urls.py。因此,咱們在test_project/urls.py
中添加如下一行。
url(r'^some_app/', include('some_app.urls'))
在some_app
的urls.py文件中添加如下內容。
url(r'^home$', direct_to_template, {"template": "some_app/home.html"})
建立一個名爲templates的目錄,而後將其添加進TEMPLATE_DIRS
。我在manage.py同級目錄下建立templates。
將templates添加進TEMPLATE_DIRS
我須要作如下設定,若是你也使用跟我同樣的目錄結構,你也須要一樣的設定。
PROJECT_DIR = os.path.dirname(__file__) TEMPLATE_DIRS = ( os.path.join(PROJECT_DIR, '../templates'), )
咱們須要爲some_app
建立home.html文件,而後你須要進入templates目錄。因此建立templates/come_app/home.html,在文件中寫入如下內容。
<html> <body> <h1>This is home for some_app</h1> </body> </html>
如今查看一下項目的目錄結構,便於消除一些不清楚的地方。
~/staticvirt/test_project$ tree -I *.pyc . |-- manage.py |-- some_app | |-- __init__.py | |-- models.py | |-- tests.py | |-- urls.py | *-- views.py |-- templates | *-- some_app | *-- home.html *-- test_project |-- __init__.py |-- settings.py |-- urls.py *-- wsgi.py 4 directories, 11 files
咱們不想一想是.pyc文件,因此將他們作了過濾。
啓動服務。請確保你作好了你的數據庫設定。
(staticvirt)~/staticvirt/test_project$ python manage.py runserver
在瀏覽器中打開http://127.0.0.1:8000/some_app/home
。從如今開始,咱們稱這個頁面爲some_app的home,你應該可以看到你剛寫下的html的內容。
讓咱們編輯下some_app
中的home.html文件,而且在其中添加樣式,如今還不存在任何樣式文件,咱們將在編輯好home.html中的代碼後添加。
<html> <head> <link href="{{STATIC_URL}}styles.css" rel="stylesheet" type="text/css"> </head> <body> <h1>This is home for some_app</h1> </body> </html>
刷新some_app
的home頁面。你將不會看到任何變化,由於咱們尚未建立樣式文件。
一樣,訪問http://127.0.0.1/static/style.css
,你將會看到一個404頁面。
如今開始建立樣式文件。由於咱們想要在some_app
的template中使用這個樣式,因此咱們將在some_app
的static/的子目錄中建立。因此建立some_app/static/style.css
,添加如下內容。
body { background-color: red; }
再刷新some_app
的home頁面,你將會看到頁面背景變成了紅色。一樣,訪問http://127.0.0.1/static/style.css
,你看到的再也不是404頁面,而是樣式文件的內容。若是你看到這些變化,請確認你將some_app
添加進了INSTALLED_APPS
,而且重啓了服務。
python manage.py collectstatic
。 STATIC_URL, STATIC_ROOT, STATICFILES_FINDERS, STATICFILES_DIRS
。 INSTALLED_APPS
。 STATIC_ROOT
和STATICFILES_DIRS
。即便你將他們註釋或者刪除,你的項目依然可以像如今同樣工做。 INSTALLED_APPS
,若是咱們想要使用Django默認的靜態文件處理服務。 python manage.py runserver
。 STATIC_URL
下處理靜態文件。注意STATIC_URL
已經設置爲'/static/'。這就是爲何咱們獲取到了咱們的靜態文件,舉個例子,樣式文件在這個url下http://127.0.0.1:8000/static/styles.css
。http://127.0.0.1:8000/static_changed/styles.css
,你將會獲得一個404頁面。若是你想要在http://127.0.0.1:8000/static_changed/styles.css
提供,須要設置STATIC_URL = '/static_changed/'
。如今動手試試吧。這只是爲了舉例說明STATIC_URL的用處,如今都改回默認設置,即STATIC_URL = '/static/'
。 STATICFILES_FINDERS
的做用了。STATICFILES_FINDERS
中咱們有兩條記錄: 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder'
如今你能夠先無論FileSystemFinder,若是你願意,你能夠先註釋掉這一行。AppDirectoriesFinder告訴Django從INSTALLED_APPS
中每個app下的static/ 子目錄下去尋找靜態文件。記住,咱們是將style.css放在了some_app
中static/子目錄下,這就是爲何Django可以找到它,而且進行正確的處理。若是你將'static/'子目錄修改成其餘名字,你的靜態文件就不能被正確處理了。動手試一試吧。註釋掉AppDirectoriesFinder這一行,而後訪問http://127.0.0.1:8000/static/styles.css
,如今樣式文件不能被正確地處理了。好,嘗試事後去掉註釋。
如今,咱們知道了STATIC_URL
和STATICFILES_FINDERS
的做用。咱們如今仍然不須要用到STATIC__ROOT
和STATICFILES_DIRS
。
爲了瞭解一些其餘的事情關於靜態文件的處理,咱們須要另外一個app。
建立一個。
python manage.py startapp other_app
修改項目的urls.py,將other_app
包括進去。如今項目的urls.py包括兩行。
url(r'^some_app/', include('some_app.urls')), url(r'^other_app/', include('other_app.urls')),
咱們須要在other_app
的urls.py中添加幾行,好比,在other_app/urls.py
中:
url(r'^home$', direct_to_template, {"template": "other_app/home.html"})
如今在templates目錄下建立other_app/home.html
。
<html> <body> <h1>This is home for other_app</h1> </body> </html>
查看一下如今的目錄結構。
~/staticvirt/test_project$ tree -I *.pyc . |-- manage.py |-- other_app | |-- __init__.py | |-- models.py | |-- tests.py | |-- urls.py | *-- views.py |-- some_app | |-- __init__.py | |-- models.py | |-- static | | *-- styles.css | |-- tests.py | |-- urls.py | *-- views.py |-- templates | |-- other_app | | *-- home.html | *-- some_app | *-- home.html *-- test_project |-- __init__.py |-- settings.py |-- urls.py *-- wsgi.py
將other_app
添加進INSTALLED_APPS
。
如今訪問url:http://127.0.0.1:8000/other_app/home
。
爲other_app的home頁面添加樣式。假設咱們想讓它的背景顏色爲藍色,咱們建立other_app/static/other_style.css
body{ background-color: blue; }
將樣式文件添加進other_app的home頁面的模板中,將templates/other_app/home.html
改成:
<html> <head> <link href="{{STATIC_URL}}other_style.css" rel="stylesheet" type="text/css"> </head> <body> <h1>This is home for other_app</h1> </body> </html>
刷新http://127.0.0.1:8000/other_app/home
,你將會看到藍色背景。你也許須要重啓服務才能看到變化。一樣,咱們可以在http://127.0.0.1:8000/static/other_style.css
中看到樣式文件的內容。
同時,訪問http://127.0.0.1:8000/some_app/home
,驗證下some_app的home頁面依然是紅色背景。
當咱們發起一個/static/other_style.css
的請求,Django知道STATIC_URL
設置爲'/static/',這跟url提供的第一個部分相匹配,所以它推斷咱們想要將其做爲靜態文件處理,因此它進入全部app的static/子目錄中進行查找,由於STATICFILES_FINDERS
包含了'django.contrib.staticfiles.finders.AppDirectoriesFinder'。當它在other_app
中的static/目錄下找到一個名爲other_style.css
的文件,就對它進行處理。
然而,這帶來了另外一個問題,你必定注意到了咱們將other_app
中的樣式文件命名爲other_style.css
。若是咱們想要它的名稱也爲style.css會發生什麼呢?試試看。
mv other_app/static/other_style.css other_app/static/styles.css
同時,咱們須要修改other_app的home文件來引入這個樣式文件。咱們必須作這個,由於咱們將other_style.css
更名爲了style.css。other_app
的home文件修改以下:
<html> <head> <link href="{{STATIC_URL}}styles.css" rel="stylesheet" type="text/css"> </head> <body> <h1>This is home for other_app</h1> </body> </html>
如今查看兩個咱們建立的頁面。
http://127.0.0.1:8000/some_app/home http://127.0.0.1:8000/other_app/home
你會發現如今兩個頁面的背景都變成了紅色。這依賴於INSTALLED_APPS中app的排列順序。若是some_app
在other_app
的前面,兩個頁面都會是紅色背景。若是other_app
在some_app
的前面,那麼兩個頁面背景都是藍色。在個人設置中,some_app
在other_app
以前,因此背景都是紅色的。
兩個頁面都想引用一個名爲style.css的靜態文件。Django嘗試在INSTALLED_APPS中列出的全部app中的static/子目錄下尋找這個文件。一旦它在some_app
的static/子目錄中找到了,就會進行處理而且再也不繼續在other_app
中進行尋找。所以,some_app
中static/子目錄下將背景設置爲紅色,那麼兩個頁面都被設置爲紅色背景了。
那麼,若是咱們想在兩個app中樣式文件都叫作style.css怎麼作?這時候,咱們須要在沒一個app下的static/目錄下增長一層目錄,將其命名爲各自app的名稱。像下面這麼作:
mkdir some_app/static/some_app mv some_app/static/styles.css some_app/static/some_app mkdir other_app/static/other_app mv other_app/static/styles.css other_app/static/other_app/
咱們在每個app下的static/子目錄下建立一個與各自app相同的目錄。而後將樣式文件移到這個目錄下。
同理,也須要修改各自的模板文件。
修改templates/some_app/home.html
中的stylesheet路徑,新的內容以下:
<html> <head> <link href="{{STATIC_URL}}some_app/styles.css" rel="stylesheet" type="text/css"> </head> <body> <h1>This is home for some_app</h1> </body> </html>
對templates/other_app/home.html
作類似的改動。
<html> <head> <link href="{{STATIC_URL}}other_app/styles.css" rel="stylesheet" type="text/css"> </head> <body> <h1>This is home for other_app</h1> </body> </html>
如今再次查看兩個頁面。
http://127.0.0.1:8000/some_app/home http://127.0.0.1:8000/other_app/home
你將會發現一個背景是紅色,另外一個是藍色。
some_app
的模板須要引用http://127.0.0.1:8000/static/some_app/styles.css
。 STATIC_URL
匹配,推測這須要處理靜態文件some_app/style.css。 some_app/style.css
。 some_app
的static/子目錄中找到了它,並進行處理。 other_app
的模板須要引用http://127.0.0.1:8000/static/other_app/styles.css
。 other_app/style.css
。 other_app
的static/子目錄中找到了它,並進行處理。 但願你如今對於STATIC_URL, STATICFILES_FINDERS和靜態文件是怎麼處理的更加清楚了。
到如今咱們假定咱們在some_app
和other_app
是須要各自獨立的靜態文件,因此咱們爲他們寫了不一樣樣式文件。
假定咱們項目中一些樣式須要保持一致,沒一個app都沒有特殊。這也的話,咱們不須要將這些樣式文件放進任何一個app的static/子目錄中。咱們在manage.py的同級目錄中建立一個目錄,而後將項目共同的靜態資源放在這個目錄中。
然咱們看看是怎麼作的。
在manage.py的同一級下建立一個名爲project_static的目錄。
mkdir project_static
建立一個名爲base.css的文件,放進去。
touch project_static/base.css
編輯這個頁面,包含如下內容:
h1 { font-style: italic; }
咱們想讓項目中全部h1標籤中的內容斜體顯示。
Django如今還不知道這個文件,也不知道怎麼進行處理。要讓Django知道它,須要將包含這個文件的目錄添加進STATICFILES_DIRS。因此編輯test_project/settings.py
,將須要的目錄添加進STATICFILES_DIRS。
STATICFILES_DIRS = ( os.path.join(PROJECT_DIR, '../project_static'), )
試着訪問http://127.0.0.1:8000/static/base.css
,你應該能看到剛纔寫的樣式。請確保在STATICFILES_FINDERS
中你設置了:
'django.contrib.staticfiles.finders.FileSystemFinder'
不然你將獲得一個404頁面。
STATICFILES_DIRS
設定的全部目錄中尋找這個靜態文件,好比base.css。 STATICFILES_DIRS
中指定了一個目錄,即project_static
,Django服務器在這個目錄中嘗試尋找這個文件。它在這個目錄中進行搜索時找到了這個文件,而後進行處理。 STATICFILES_DIRS
指定的目錄中找到這個文件,它將會在INSTALLED_APPS
下全部app的static/子目錄嘗試尋找。 staticfiles_urlpatterns()
。 爲了在模板中使用這個文件,咱們須要引用這個樣式。在全部模板中添加進下面這行。
<link href="{{STATIC_URL}}base.css" rel="stylesheet" type="text/css">
刷新兩個頁面的url,你將會看到這些頁面中h1標籤中的字體都爲斜體。
讓咱們查看最終的目錄結構,若是你有什麼問題能夠有幫助。
(staticvirt)~/staticvirt/test_project$ tree -I *.pyc . |-- manage.py |-- other_app | |-- __init__.py | |-- models.py | |-- static | | *-- other_app | | *-- styles.css | |-- tests.py | |-- urls.py | *-- views.py |-- project_static | *-- base.css |-- some_app | |-- __init__.py | |-- models.py | |-- static | | *-- some_app | | *-- styles.css | |-- tests.py | |-- urls.py | *-- views.py |-- templates | |-- other_app | | *-- home.html | *-- some_app | *-- home.html *-- test_project |-- __init__.py |-- settings.py |-- urls.py *-- wsgi.py 11 directories, 20 files
STATICFILES_DIRS
中找到的和在全部app下的static/子目錄中找到的靜態資源),將它們放進一個STATIC_ROOT
定義的位置。 讓咱們驗證一下,建立一個名爲static_resources
的目錄.
mkdir static_resources
修改settings.py,添加如下幾行.
STATIC_ROOT = os.path.join(PROJECT_DIR, '../static_resources')
如今運行命令:
python manage.py collectstatic
它會請求你確認,輸入'yes',而後你將會看見全部的靜態資源被收集進一個你在STATIC_ROOT
定義的目錄中。
而後在生產服務器中你能夠設置全部的靜態文件請求都進入STATIC_ROOT
定義的目錄中進行查找。
再說一次,關於STATIC_ROOT
的部分只是附帶着說說。在開發階段你都不須要用到它。