一、首先需要了解的知識點是:
1、出於對效率和安全的考慮,django管理靜態文件的功能僅限於在開發階段的debug模式下使用,且需要在配置文件的INSTALLED_APPS中加入django.contrib.staticfiles(django工程創建后默認已經安裝),網站正式部署上線后,靜態文件是由Nginx等服務器管理。
二、接下來看下如何配置和引入靜態文件
先把工程的目錄結構展示出來,方便后文敘述
相關配置:
1、首先確保在配置文件的INSTALLED_APPS中加入了 django.contrib.staticfiles(默認已加入)
2、在配置文件中配置STATIC_URL,如:
STATIC_URL="/st/" # STATIC_URL的作用是用於拼接靜態文件的存儲路徑。
3、在配置文件中配置STATICFILES_DIRS為靜態靜態文件的存儲路徑,比如:
STATICFILES_DIRS = [ os.path.join(BASE_DIR, "static") # 即靜態文件存放在 BASE_DIR/static 下(和manage.py同級目錄下),注意BASE_DIR指django工程的絕對路徑 ]
配置完成之后就可以在模板中導入靜態文件了
引入靜態文件:
1、在模板文件中導入static模板標簽,即在模板文件的開頭處寫上:{% load static %}
說明:static模板標簽(即{% static "url" %}標簽)並不是django內置的模板標簽,而是屬於自定義模板標簽,所以我們不能直接使用,需要先導入該模板標簽才行。
那么這個標簽在哪里定義的呢?如果是pycharm,直接在{% load static %}中,把光標放在static上,按ctr+b定位到定義處,如下圖:
根據注釋,我們可以看出這個模板標簽的作用就是傳遞一個靜態文件的相對路徑(即形參path),返回該靜態文件的絕對路徑。
2、使用{% static "url.."%}標簽引入靜態文件
第1步中我們已經導入了static模板標簽,也了解了它的作用,下面就可以使用它引入靜態文件了。先給個例子,方便解釋,比如我們需要在模板中引入/static/css/下的bootstrap.css,那么就應該這么寫:
<link rel="stylesheet" href="{% static 'css/bootstrap.css' %}">
至於為什么路徑中的/static/沒寫在static標簽處,我們等下再解釋。
結合static函數的源碼(即static標簽定義),上面link標簽中的static模板標簽的含義就是,把bootstrap.css的相對路徑'css/bootstrap.css'傳給了static函數的path形參,所以它應該給我們返回一個該靜態文件的絕對路徑。由於我們在上文配置中配置了STATIC_URL="/st/",所以在瀏覽器端,查看該模板對應的HTML源碼,可以發現django把上面這個標簽渲染出來的結果是:
<link rel="stylesheet" href="/st/css/bootstrap.css">
"/st/css/bootstrap.css"就是static標簽返回的絕對路徑,那么為什么前面多個/st/?這是我們留下的第二個疑問,往后讀就能找到答案。
現在解釋上面留下的第一個疑問,為什么路徑中的/static/沒寫在static標簽處?這個又涉及到一個配置:
關於這個配置,不做深入探討,我們只需要簡單了解他的作用即可,具體信息考參考官網(https://docs.djangoproject.com/en/2.2/ref/settings/#std:setting-STATICFILES_FINDERS)
官網給出的說明就是,django在查找靜態文件的時候,首先會在STATICFILES_DIRS指定的路徑中尋找,找不到就會在各個app下的static文件夾下面找,由於我們在配置文件中已經指定了static文件夾,也就是說已經告訴了django,首先去static文件夾中找指定的靜態文件,所以上面的static標簽就會自動去static文件夾中去找css下的bootstrap.css這個靜態文件,所以就沒必要再把/static/寫上了,否則就成了告訴django去static文件夾下的static/css/找bootstrap.css,這樣就會找不到了。
至此,我們已經知道了如何引入static標簽,以及使用static標簽引入靜態文件,順帶也把STATICFILES_DIRS配置的作用說明了,還有一個模糊的地方就是STATIC_URL配置是個什么鬼,為什么django會把上面static標簽返回的絕對路徑前面加一個/st/?
要說明STATIC_URL的作用,首先要捋一捋django處理http請求的過程:瀏覽器發送一個http請求,django的url解析器解析url,然后匹配到相應的視圖函數處理請求。再看django最終把我們上面的標簽渲染成如下:
<link rel="stylesheet" href="/st/css/bootstrap.css">
那么瀏覽器去請求這個靜態文件的時候,其完整請求路徑應該是http://localhost:8000/st/css/bootstrap.css,django是如何解析這個請求路徑,然后找到相應的靜態文件並返回的呢?
回憶一下我們開頭講的,要在django中管理靜態文件,需要安裝django.contrib.staticfiles這個APP,所以猜測,django處理這個請求都是在這個APP中完成的,進入到這個APP
發現這個APP結構和我們自定義的APP差不多,猜測django處理上述靜態文件路徑(解析路徑,路由到視圖函數處理請求等)就是在urls.py中完成的,點開:
看到上圖中的urlpatterns = [],是不是熟悉的感覺?
在點開截圖中橢圓形框出的static函數,看干了什么
看到re_path()是不是更熟悉的感覺?其實這個APP解析url和路由到指定視圖函數跟我們自定義的APP邏輯是一樣的。
很簡單,就是把url中的前綴/st/提取出來,作為正則表達式的匹配字符串,也就是說,瀏覽器發出的http:8000/st/css/bootstrap.css的請求,由於該地址前綴是/st/,所以會被這個規則匹配到,從而路由到相應的視圖函數進一步處理。
這樣,我們就明白了STATIC_URL配置項的作用了,就是使用{% static "url.." %}時,把STATIC_URL配置的字符串拼接到靜態文件的路徑上作為其前綴,以便於在django.contrib.staticfiles這個APP解析出靜態文件的真正路徑,然后帶着這個真正路徑去STATICFILES_DIRS配置的路徑下找,找不到就去每個APP下的static文件夾中找。
所以說,STATIC_URL配置的字符串只是個符號,你想寫啥都行(當然要守規矩)。
另外的注意事項:
在我們配置的{% static 'css/bootstrap.css' %},中,如果寫成{% static '/css/bootstrap.css' %}也就是css前面有個"/",那么django就會認為這是一個絕對路徑,而不會把STATIC_URL配置項加到css前面,官網:https://docs.djangoproject.com/en/2.2/topics/forms/media/#form-asset-paths 中的Paths in asset definitions條目
還有STATIC_ROOT配置,參見:https://docs.djangoproject.com/en/2.2/ref/settings/#std:setting-STATICFILES_STORAGE