1. 程式人生 > >Django - 配置、靜態檔案與路由

Django - 配置、靜態檔案與路由

1 配置檔案

1.1 BASE_DIR

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

當前工程的根目錄,Django會依此來定位工程內的相關檔案,我們也可以使用該引數來構造檔案路徑。

1.2 DEBUG

除錯模式,建立工程後初始值為True,即預設工作在除錯模式下。

作用:

  • 修改程式碼檔案,程式自動重啟

  • Django程式出現異常時,向前端顯示詳細的錯誤追蹤資訊,例如

    而非除錯模式下,僅返回Server Error (500)

注意:部署線上執行的Django不要執行在調式模式下,記得修改DEBUG=False。

1.3 本地語言與時區

Django支援本地化處理,即顯示語言與時區支援本地化。

本地化是將顯示的語言、時間等使用本地的習慣,這裡的本地化就是進行中國化,中國大陸地區使用簡體中文,時區使用亞洲/上海時區,注意這裡不使用北京時區表示。

初始化的工程預設語言和時區為英語和UTC標準時區

LANGUAGE_CODE = 'en-us'  # 語言
TIME_ZONE = 'UTC'  # 時區

將語言和時區修改為中國大陸資訊

LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'

2 靜態檔案

專案中的CSS、圖片、js都是靜態檔案。一般會將靜態檔案放到一個單獨的目錄中,以方便管理。在html頁面中呼叫時,也需要指定靜態檔案的路徑,Django中提供了一種解析的方式配置靜態檔案路徑。靜態檔案可以放在專案根目錄下,也可以放在應用的目錄下,由於有些靜態檔案在專案中是通用的,所以推薦放在專案的根目錄下,方便管理。

為了提供靜態檔案,需要配置兩個引數:

  • STATICFILES_DIRS 存放查詢靜態檔案的目錄
  • STATIC_URL 訪問靜態檔案的URL字首

2.1 示例

1) 在專案根目錄下建立static_files目錄來儲存靜態檔案。

2) 在demo/settings.py中修改靜態檔案的兩個引數為

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static_files'),
]

3)此時在static_files新增的任何靜態檔案都可以使用網址 /static/檔案在static_files中的路徑 來訪問了。

例如,我們向static_files目錄中新增一個index.html檔案,在瀏覽器中就可以使用127.0.0.1:8000/static/index.html來訪問。

或者我們在static_files目錄中添加了一個子目錄和檔案goods/detail.html,在瀏覽器中就可以使用127.0.0.1:8000/static/goods/detail.html來訪問。

2.2 注意

Django 僅在除錯模式下(DEBUG=True)能對外提供靜態檔案。

當DEBUG=False工作在生產模式時,Django不再對外提供靜態檔案,需要是用collectstatic命令來收集靜態檔案並交由其他靜態檔案伺服器來提供。

3 路由說明

3.1 路由定義位置

Django的主要路由資訊定義在工程同名目錄下的urls.py檔案中,該檔案是Django解析路由的入口。

每個子應用為了保持相對獨立,可以在各個子應用中定義屬於自己的urls.py來儲存該應用的路由。

from django.conf.urls import url
from . import views

# urlpatterns是被django自動識別的路由列表變數
urlpatterns = [
    # 每個路由資訊都需要使用url函式來構造
    # url(路徑, 檢視)
    url(r"^index/$", views.index, name="index"),
]

然後用主路由檔案包含各應用的子路由資料。

from django.conf.urls import url
from django.contrib import admin
import users.views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r"^users/", include("user.urls", namespace="users")),
]

除了上述方式外,也可將工程的全部路由資訊都定義在主路由檔案中,子應用不再設定urls.py。如:

from django.conf.urls import url
from django.contrib import admin
import users.views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^users/index/$', users.views.index)
]

3.2 路由解析順序

Django在接收到一個請求時,從主路由檔案中的urlpatterns列表中以由上至下的順序查詢對應路由規則,如果發現規則為include包含,則再進入被包含的urls中的urlpatterns列表由上至下進行查詢。

值得關注的由上至下的順序,有可能會使上面的路由遮蔽掉下面的路由,帶來非預期結果。例如:

urlpatterns = [
    url(r'^say', views.say),
    url(r'^sayhello', views.sayhello),
]

即使訪問sayhello/路徑,預期應該進入sayhello檢視執行,但實際優先查詢到了say路由規則也與sayhello/路徑匹配,實際進入了say檢視執行。

提示:

需要注意定義路由的順序,避免出現遮蔽效應。(可以新增“$”來避免這種情況)

3.3 路由命名與reverse反解析(逆向)

3.3.1 路由命名

在定義路由的時候,可以為路由命名,方便查詢特定檢視的具體路徑資訊。

1) 在使用include函式定義路由時,可以使用namespace引數定義路由的名稱空間,如

url(r'^users/', include('users.urls', namespace='users')),

名稱空間表示,凡是users.urls中定義的路由,均屬於namespace指明的users名下。

名稱空間的作用:避免不同應用中的路由使用了相同的名字發生衝突,使用名稱空間區別開。

2) 在定義普通路由時,可以使用name引數指明路由的名字,如

urlpatterns = [
    url(r'^index/$', views.index, name='index'),
    url(r'^say', views.say, name='say'),
]

3.3.2 reverse反解析

使用reverse函式,可以根據路由名稱,返回具體的路徑,如:

from django.core.urlresolvers import reverse  # 注意導包路徑

def index(request):
    return HttpResponse("hello the world!")

def say(request):
    url = reverse('users:index')  # 返回 /users/index/
    print(url)
    return HttpResponse('say')
  • 對於未指明namespace的,reverse(路由name)
  • 對於指明namespace的,reverse(名稱空間namespace:路由name)

3.4 路徑結尾斜線/的說明

Django中定義路由時,通常以斜線/結尾,其好處是使用者訪問不以斜線/結尾的相同路徑時,Django會把使用者重定向到以斜線/結尾的路徑上,而不會返回404不存在。如

urlpatterns = [
    url(r'^index/$', views.index, name='index'),
]

使用者訪問 index 或者 index/ 網址,均能訪問到index檢視。

說明:

雖然路由結尾帶/能帶來上述好處,但是卻違背了HTTP中URL表示資源位置路徑的設計理念。

是否結尾帶“/”以所屬公司定義風格為準。

4 App應用配置

在每個應用目錄中都包含了apps.py檔案,用於儲存該應用的相關資訊。

在建立應用時,Django會向apps.py檔案中寫入一個該應用的配置類,如

from django.apps import AppConfig

class UsersConfig(AppConfig):
    name = 'users'

我們將此類新增到工程settings.py中的INSTALLED_APPS列表中,表明註冊安裝具備此配置屬性的應用。

  • AppConfig.name 屬性表示這個配置類是載入到哪個應用的,每個配置類必須包含此屬性,預設自動生成。

  • AppConfig.verbose_name 屬性用於設定該應用的直觀可讀的名字,此名字在Django提供的Admin管理站點中會顯示,如

from django.apps import AppConfig

class UsersConfig(AppConfig):
    name = 'users'
    verbose_name = '使用者管理'