Django 路由層,檢視層,模板層
MVC與MTV模型
一、MVC
Web伺服器開發領域裡著名的MVC模式,所謂MVC就是把Web應用分為模型(M),控制器(C)和檢視(V)三層,他們之間以一種外掛式的、鬆耦合的方式連線在一起,模型負責業務物件與資料庫的對映(ORM),檢視負責與使用者的互動(頁面),控制器接受使用者的輸入呼叫模型和檢視完成使用者的請求,其示意圖如下所示:
二、MTV
Django的MTV模式本質上和MVC是一樣的,也是為了各元件間保持鬆耦合關係,只是定義上有些許不同,Django的MTV分別是:
- M 代表模型(Model): 負責業務物件和資料庫的關係對映(ORM)。
- T 代表模板 (Template):負責如何把頁面展示給使用者(html)。
- V 代表檢視(View): 負責業務邏輯,並在適當時候呼叫Model和Template。
- 除了以上三層之外,還需要一個URL分發器,它的作用是將一個個URL的頁面請求分發給不同的View處理,View再呼叫相應的Model和Template,MTV的響應模式如下所示:
Django的下載與基本命令
- 下載Django:pip3 install django==2.0.1
- 建立一個django project: django-admin.py startproject luffy
- 在mysite目錄下建立應用:python manage.py startapp app01
- 啟動django專案:python manage.py runserver 8080 我們訪問:http://127.0.0.1:8080/時就可以看到:
一、檔案介紹
- manage.py ----- Django專案裡面的工具,通過它可以呼叫django shell和資料庫等。
- settings.py ---- 包含了專案的預設設定,包括資料庫資訊,除錯標誌以及其他一些工作的變數。
- urls.py ----- 負責把URL模式對映到應用程式。
靜態檔案
?1 2 3 4 5 |
#在settings.py中:
STATIC_URL
=
'/static/'
STATICFILES_DIRS
=
(
os.path.join(BASE_DIR,
'static'
),
)
|
路由
URL配置(URLconf)就像Django 所支撐網站的目錄。它的本質是URL與要為該URL呼叫的檢視函式之間的對映表;你就是以這種方式告訴Django,對於客戶端發來的某個URL呼叫哪一段邏輯程式碼對應執行。
一、簡單的路由配置
- 若要從URL 中捕獲一個值,只需要在它周圍放置一對圓括號。
- 不需要新增一個前導的反斜槓,因為每個URL 都有。例如,應該是^articles 而不是 ^/articles。
- 每個正則表示式前面的'r' 是可選的但是建議加上。它告訴Python 這個字串是“原始的” —— 字串中任何字元都不應該轉義
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# 在urls.py中:
from
django.urls
import
path,re_path
from
app01
import
views
# 路由配置: 路徑--------->檢視函式
urlpatterns
=
[
path(
'admin/'
, admin.site.urls),
#無名分組:捕獲的值作為位置引數傳遞給檢視函式
re_path(r
'^articles/([0-9]{4})/$'
, views.year_archive),
#year_archive(request,'2009')
re_path(r
'^articles/([0-9]{4})/([0-9]{2})/$'
, views.month_archive),
# month_archive(request,'2009','12')
re_path(r
'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$'
, views.article_detail),
# month_archive(request,'2009','12','1'),# month_archive(request,'2009','12','13')
#有名分組:捕獲的值作為關鍵字引數傳遞給檢視函式
re_path(r
'^articles/(?P<year>[0-9]{4})/$'
, views.year_archive),
# month_archive(request, year='2005')
re_path(r
'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$'
, views.month_archive),
# month_archive(request, year='2005', month='03')
re_path(r
'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$'
, views.article_detail),
# month_archive(request, year='2003', month='03', day='03')
]
|
二、分發
?1 2 3 4 5 6 7 8 9 10 11 |
# 在urls.py中:
from
django.urls
import
path, re_path, include
urlpatterns
=
[
path(
'admin/'
, admin.site.urls),
# 分發
re_path(r
"^app01/"
, include(
"app01.urls"
)),
re_path(r
"^app02/"
, include(
"app02.urls"
)),
re_path(r
"^"
, include(
"app01.urls"
)),
]
|
三、反向解析
獲得URL 的最終形式,,對於不同層級,Django 提供不同的工具用於URL 反查:
- 在模板中:使用url 模板標籤。
- 在Python 程式碼中:使用from django.urls import reverse
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# 在urls.py中:
from
django.urls
import
path,re_path,include
from
app01
import
views
urlpatterns
=
[
path(
'admin/'
, admin.site.urls),
# 反向解析
path(
'login.html/'
,views.login,name
=
"Log"
),
re_path(r
'^articles/([0-9]{4})/$'
, views.year_archive, name
=
'news-year-archive'
),
]
# 在模板中:注意引數
"""
<form action="{% url 'Log' %}" method="post"></form>
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>
<!--多個引數-->
<a href="{% url "n4" i1 i2 %}">編輯</a>
"""
#在views.py中:
from
django.urls
import
reverse
from
django.shortcuts
import
render,HttpResponse,redirect
def
redirect_to_year(request):
# 無參
url
=
reverse(
'Log'
)
print
(url)
#有參
year
=
2006
url99
=
reverse(
'news-year-archive'
, args
=
(year,))
print
(url99)
return
HttpResponse(
'OK'
)
|
四、名稱空間
名稱空間(英語:Namespace)是表示識別符號的可見範圍。一個識別符號可在多個名稱空間中定義,它在不同名稱空間中的含義是互不相干的。我們在開發專案時,會經常使用name屬性反解出URL,當不小心在不同的app的urls中定義相同的name時,可能會導致URL反解錯誤,為了避免這種事情發生,引入了名稱空間。
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# 在urls.py中:
from
django.urls
import
path, re_path, include
urlpatterns
=
[
path(
'admin/'
, admin.site.urls),
# 分發
re_path(r
"^app01/"
, include(
"app01.urls"
)),
re_path(r
"^"
, include(
"app01.urls"
)),
# 兩個應用中,URL 模式名字一樣時:
re_path(r
"^app01/"
, include((
"app01.urls"
,
"app01"
))),
re_path(r
"^app02/"
, include((
"app02.urls"
,
"app02"
))),
]
#app01中的urls.py
from
django.urls
import
path,re_path
from
app01
import
views
urlpatterns
=
[
re_path(
"index/"
,views.index,name
=
"index"
)
]
#app02中的urls.py
from
django.urls
import
path,re_path
from
app02
import
views
urlpatterns
=
[
re_path(
"index/"
,views.index,name
=
"index"
)
]
#app01中的views.py
from
django.shortcuts
import
render,HttpResponse
from
django.urls
import
reverse
def
index(reqeust):
return
HttpResponse(reverse(
"app01:index"
))
#app02中的views.py
from
django.shortcuts
import
render,HttpResponse
from
django.urls
import
reverse
def
index(reqeust):
return
HttpResponse(reverse(
"app02:index"
))
|
五、django2.0版的path
1、基本例項
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# 在urls.py中:
from
django.urls
import
path, re_path
from
app01
import
views
urlpatterns
=
[
re_path(
'articles/(?P<year>[0-9]{4})/'
, views.year_archive),
re_path(
'article/(?P<article_id>[a-zA-Z0-9]+)/detail/'
, views.detail_view),
re_path(
'articles/(?P<article_id>[a-zA-Z0-9]+)/edit/'
, views.edit_view),
re_path(
'articles/(?P<article_id>[a-zA-Z0-9]+)/delete/'
, views.delete_view),
]
"""
1.函式 year_archive 中year引數是字串型別的
2.三個路由中article_id都是同樣的正則表示式,但是你需要寫三遍,當之後article_id規則改變後,需要同時修改三處程式碼,
在Django2.0中,可以使用 path 解決以上的兩個問題。
"""
urlpatterns
=
[
path(
'articles/2003/'
, views.special_case_2003),
path(
'articles/<int:year>/'
, views.year_archive),
path(
'articles/<int:year>/<int:month>/'
, views.month_archive),
path(
'articles/<int:year>/<int:month>/<slug>/'
, views.article_detail),
]
|
2、基本規則
- 使用尖括號(<>)從url中捕獲值。
- 捕獲值中可以包含一個轉化器型別(converter type),比如使用 捕獲一個整數變數。若果沒有轉化器,將匹配任何字串,當然也包括了 / 字元。
- 無需新增前導斜槓。
3、path轉化器
Django預設支援以下5個轉化器:
- str,匹配除了路徑分隔符(/)之外的非空字串,這是預設的形式
- int,匹配正整數,包含0。
- slug,匹配字母、數字以及橫槓、下劃線組成的字串。
- uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
- path,匹配任何非空字串,包含了路徑分隔符
4、註冊自定義轉化器
對於一些複雜或者複用的需要,可以定義自己的轉化器。轉化器是一個類或介面,它的要求有三點:
- regex 類屬性,字串型別
- to_python(self, value) 方法,value是由類屬性 regex 所匹配到的字串,返回具體的Python變數值,以供Django傳遞到對應的檢視函式中。
- to_url(self, value) 方法,和 to_python 相反,value是一個具體的Python變數值,返回其字串,通常用於url反向引用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# urls.py:
from
django.urls
import
register_converter, path
from
app01
import
yearconvert,views
#使用register_converter 將其註冊到URL配置中:
register_converter(yearconvert.FourDigitYearConverter,
'yyyy'
)
urlpatterns
=
[
path(
'articles/<yyyy:year>/'
, views.year_archive),
]
#app01.yearconvert.py:
class
FourDigitYearConverter:
regex
=
'[0-9]{4}'
#規則
def
to_python(
self
, value):
return
int
(value)
# 在這轉換了型別
def
to_url(
self
, value):
return
'%04d'
%
value
#app01.views.py:
from
django.shortcuts
import
render,HttpResponse,redirect
def
year_archive(request,year):
print
(year,
type
(year))
return
HttpResponse(
'ok'
)
|
檢視
一個檢視函式,簡稱檢視,是一個簡單的Python 函式,它接受Web請求並且返回Web響應。響應可以是一張網頁的HTML內容,一個重定向,一個404錯誤,一個XML文件,或者一張圖片. . . 是任何東西都可以。無論檢視本身包含什麼邏輯,都要返回響應。程式碼寫在哪裡也無所謂,只要它在你的Python目錄下面。除此之外沒有更多的要求了。為了將程式碼放在某處,約定是將檢視放置在專案或應用程式目錄中的名為views.py的檔案中。
一、HttpRequest物件
django將請求報文中的請求行、首部資訊、內容主體封裝成 HttpRequest 類中的屬性。
1.request屬性
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |