一、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的響應模式如下所示:
一般是用戶通過瀏覽器向我們的服務器發起一個請求(request),這個請求回去訪問視圖函數,(如果不涉及到數據調用,那么這個時候視圖函數返回一個模板也就是一個網頁給用戶),視圖函數調用模型,模型去數據庫查找數據,然后逐級返回,視圖函數把返回的數據填充到模板中空格中,最后返回網頁給用戶。
二、Django下載安裝
1、下載Django:
1
|
pip3 install django==1.11.9
|
Django我們用的是1.11.9版本,大版本就是一版本,不要下載2版本。有一些功能是有差別的。
我們下載的類似於一個模塊,借助這個模塊我們可以創建項目,而不是直接下載了項目,一定要有所區分。
1.11 是17年開始的,支持時間很長。2.2 也是長期支持的。
2、創建一個django project
創建Django項目不能用中文,我建議大家先創建一個Django_projects的文件夾,以后我們創建的jango項目全部放到這個文件夾中。接下來我們cd切換到這個目錄下,創建第一個項目:
1
|
django
-
admin startproject mysite 創建了一個名為"mysite"的Django 項目:
|
當你通過上面的命令創建一個項目時,你可能會遇到這樣的錯誤:django-admin不是內部或者外部命令,這樣是報錯了,為什么? 為什么你輸入python 輸入pip都不回報錯? python pip都是一個可執行程序,他的路徑肯定是在環境變量中,所以我們要將django-admin.exe路徑配置到環境變量中:
如果你在上面路徑找不到這個django-admin.exe,那么就通過下面的方式尋找:
通過pip安裝的大部分模塊一般都在lib>site-packages里面,在找到django-admin.exe以及django-admin.py兩個文件,
當前目錄下會生成mysite的工程,目錄結構如下:(大家注意昂,pip下載下來的django你就理解成一個模塊,而不是django項目,這個模塊可以幫我們創建django項目)
- manage.py ----- Django項目里面的工具,通過它可以調用django shell和數據庫,啟動關閉項目與項目交互等,不管你將框架分了幾個文件,必然有一個啟動文件,其實他們本身就是一個文件,類似於我們之前講的start.py。
- settings.py ---- 包含了項目的默認設置,包括數據庫信息,調試標志以及其他一些工作的變量。
- urls.py ----- 負責把URL模式映射到應用程序。
- wsgi.py ---- runserver命令就使用wsgiref模塊做簡單的web server,后面會看到renserver命令,所有與socket相關的內容都在這個文件里面了,目前不需要關注它。
這里有的同學可能使用的是虛擬環境創建的項目,那么什么是虛擬環境?簡單描述就是Python虛擬環境的主要目的是為了給不同的工程創建互相獨立的運行環境。在虛擬環境下,每一個工程都有自己的依賴包,而與其它的工程無關。不同的虛擬環境中同一個包可以有不同的版本。並且,虛擬環境的數量沒有限制,我們可以輕松地用virtualenv或者pyenv等工具來創建多個虛擬環境。
有關虛擬環境的兩篇博客:
python manage.py runserver 127.0.0.1:8080 # 此時已經可以啟動django項目了,只不過什么邏輯也沒有呢
3、創建應用
你會發現,上面沒有什么view視圖函數的文件啊,這里我們說一個應用與項目的關系,上面我們只是創建了一個項目,並沒有創建應用,以微信來舉例,微信是不是一個大的項目,但是微信里面是不是有很多個應用,支付應用、聊天應用、朋友圈、小程序等這些在一定程度上都是相互獨立的應用,也就是說一個大的項目里面可以有多個應用,也就是說項目是包含應用的,它沒有將view放到這個項目目錄里面是因為它覺得,一個項目里面可以有多個應用,而每個應用都有自己這個應用的邏輯內容,所以他覺得這個view應該放到應用里面,比如說我們的微信,剛才說了幾個應用,這幾個應用的邏輯能放到一起嗎,放到一起是不是就亂套啦,也不好管理和維護,所以這些應用的邏輯都分開來放,它就幫我們提煉出來了,提煉出來一個叫做應用的東西,所以我們需要來創建這個應用。
通過django命令創建的項目:他認為你的項目我已經給你創建好包含(服務器相關應用以及url等)。但是你的應用邏輯需要自己完成。也就是說咱們的項目中必須創建應用。
python manage.py startapp blog # 通過執行manage.py文件來創建應用,執行這句話一定要注意,你應該在這個manage.py的文件所在目錄下執行這句話,因為其他目錄里面沒有這個文件 python manage.py startapp blog2
# 每個應用都有自己的目錄,每個應用的目錄下都有自己的views.py視圖函數和models.py數據庫操作相關的文件 # 上面我是在一個項目中創建了兩個應用,就好比你創建微信項目,開啟了聊天和搖一搖兩個應用一樣。
我們現在只需要看其中兩個文件
models.py :之前我們寫的那個名為model的文件就是創建表用的,這個文件就是存放與該app(應用)相關的表結構的
views.py :存放與該app相關的視圖函數的
4、啟動項目
python manage.py runserver 8080 # python manage.py runserver 127.0.0.1:8080,本機就不用寫ip地址了 如果連端口都沒寫,默認是本機的8000端口
這樣我們的django就啟動起來了!當我們訪問:http://127.0.0.1:8080/時就可以看到:
學習Django,我們就學上面的這些文件,怎么在MTV+url分發的功能下來使用。
5、通過pycharm創建Django項目以及應用
最終你的目錄結構就是這個樣子:
三、基於Django項目實現簡單的登錄示例
接下來,我們基於Django項目實現一個簡單的登錄,將整個流程走通。
按照我們之前自己寫的起飛版web項目,主要是兩部分,服務器程序以及應用程序,在Django項目中服務器程序已經給我們封裝好了,基本上學一些參數即可,比較容易,主要是應用程序,所以我們第一步先配置應用程序,應用程序的第一步在哪?啟動項目,在瀏覽器輸入ip端口,回車,這樣服務端接收到路徑根據不同的路徑執行對應的函數,所以我們先配置路徑url.
1、配置url
from app01 import views # 必須引用views模塊
urlpatterns = [
# url(r'^admin/', admin.site.urls), 這個路徑拼接的admin組件,后面我們會講到。 url(r'^index/', views.login), ]
這里是通過正則匹配匹配的路徑,前面固定拼接的就是'127.0.0.1:8000',現在你這樣寫'/index/' ,后面映射的就是views.py視圖函數的login,因為是正則匹配,所以如果你訪問的是這樣的路徑:'http://127.0.0.1:8000/index/login/666',也是可以映射到此函數的,你要想完全匹配的話應該這樣寫:
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [ # url(r'^admin/', admin.site.urls), 這個路徑拼接的admin組件,后面我們會講到。 url(r'^index$', views.login), ]
下面是django2.x版本的url寫法,不太一樣了,但是兼容1.x的,不過我們現在還是主要說1.xx版本的,所以寫url的時候按照上的方式寫。
from django.contrib import admin from django.urls import path
from app01 import views
#找對應的函數,是哪個app里面的函數 from app01 import views urlpatterns = [ path('admin/', admin.site.urls), #這個先不用管,后面會學 path('index/',views.index), ]
這樣通過瀏覽器只能輸入http://127.0.0.1:8000/index此url才可以映射到login函數。
2、配置views視圖函數
找到views文件,定義一個login函數,之前我們自己寫的時候可以接受形參envison,現在我們可以設置任意形式參數,一般我們設置為request,request參數就包含了服務器程序的請求響應所有的參數提供給我們使用。
from django.shortcuts import render, HttpResponse
def login(request): print(request) # <WSGIRequest: GET '/index'> 這是一個對象 print(request.method) # method方法返回的就是請求方式,本次請求就是get請求 return HttpResponse('跑通了,好玩么?') # 返回給頁面一行字符串,一般都是測試是否跑通了。
那么如何返回一個html頁面呢? 這里就需要引用另一個功能,就是render。之前jinja2有一個template通過render進行前后端渲染,現在django也給我們提供了一個render方法,可以給瀏覽器返回一個頁面,並且能進行前后端的渲染。我們要完成的就是登錄功能,所以我們下面寫一個登錄頁面login.html。現在我們現在views文件中返回。
from django.shortcuts import render, HttpResponse def login(request): return render(request,'login.html') # 第一個參數必須是request參數,因為request包含的是服務器程序的請求與響應所有信息,所以你返回給誰也就是給誰響應都在request里面,第二個參數就是html頁面。
3、配置template
接下來我們要完善html頁面,再此之前我們需要配置一下template的路徑,讓django可以找到(有的默認已經配置好了)。
在settings文件中配置:
路徑配置成功之后,我們寫一個登錄的頁面。
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Bootstrap 101 Template</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <h1>歡迎訪問xx系統,請先登錄</h1> <form action="/index/" method="post"> 用戶名:<input type="text" name="username"> 密碼:<input type="password" name="password"> 提交:<input type="submit"> </form> </body> </html>
form表單兩點注意:
1. action路徑 index前面一定要主動加上‘/’,如果你不主動加上/,則最終路徑會給你拼接成:http://127.0.0.1:8000/index/index/
2. form表單為什么用post提交數據?
你訪問頁面以及form表單提交數據都是通過http://127.0.0.1:8000/index此url也就是說都必須執行login函數,如果都是get請求,那么login函數如何區分哪個get是請求頁面哪個get是提交數據呢?所以要用post請求提交數據。
4、完善views視圖函數
之前寫的views視圖函數我們只完成了返回一個頁面的功能,現在不僅是返回頁面,我們應該處理post提交的數據,怎么處理?每次請求都是經過此函數,所以我們要對這兩次請求加以區分,怎么區分?我們要判斷請求方式是get還是post,通過request.method判斷即可,那么如何獲取提交過來的數據呢?如果是get請求的數據通過request.GET.get獲取,如果是post請求的數據通過request.POST.get獲取。所以我們views函數這樣完成。
def login(request): if request.method == 'POST': print(request.POST) # <QueryDict: {'username': ['taibai '], 'password': ['123']}> username = request.POST.get('username').strip() password = request.POST.get('password').strip() print(username) if username == 'taibai' and password == '123': return HttpResponse('登錄成功') else: return HttpResponse('登錄失敗') else: return render(request, 'login.html')
post提交數據時你們可能會遇到這種情況:
現在只需要做一步,在settings配置文件里面將這一行注釋掉,這是django給你加的一個csrf的認證,現在不需要,我們會講的
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
還記得django寫視圖函數的時候,有一個參數是必須要給的嗎,叫做request,如果你是post請求,那么就用request.POST,就能拿到post請求提交過來的所有數據(一個字典,然后再通過字典取值request.POST.get('username'),取出來的就是個字符串,你在那個字典里面看到的是{'username':['taibai']},雖然看着是列表,但是request.POST.get('username')取出來的就是個字符串),通過request.GET就能拿到提交過來的所有數據,而且記着,每一個視圖函數都要給人家返回一些內容,用render或者HttpResponse等,其實render里面也是通過HttpResponse來返回內容,不然會報錯,錯誤是告訴你沒有返回任何內容:
django認識了,以后我們就按照下面的步驟來學:
1.django的url控制器
2.django的視圖
3.django的模板(template)
4.ORM(花的時間比較久)
做一個小總結
目前我們學過的一些參數:
render:返回給瀏覽器一個html頁面,第一個參數一定是request。 HttpResponse:返回給瀏覽器一個字符串數據。 request 包含請求相應的服務器程序所有信息。 request.method:請求方法,返回大寫的GET,POST。 request.POST:post請求的數據,返回一個querydict. request.POST.get('鍵'):返回對應的值 request.GET: post請求的數據,返回一個querydict. request.GET.get('鍵'):返回對應的值。