MVT三大塊之view(視圖)

1.視圖簡介

  做用:接受web請求,返回web響應html

  本質:一個函數,定義在views.py文件中(定義在其餘地方也行,約定俗成)python

  流程:(若是匹配不到,報一個404錯誤)-----結果返回http response對象mysql

1.1 視圖配置

  在settings.py文件的ROOT_URLCONF部分指定根級url的配置(指向urls.py文件)web

查找流程,mannage.py→settings.py→urls.py正則表達式

習慣上,每一個應用(APP)單獨配置本身的urls.py,不寫在根目錄,防止由於應用過多,看起來太混亂很差維護,sql

配置本身的url:只需建立應用後在應用文件中建立urls.py文件(在根目錄中包含)數據庫

1.2 簡單的演示

根目錄下的urls.py文件django

from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
	url(r'^admin/', admin.site.urls),
	url(r'^booktest/', include('booktest.urls')),
] 

app目錄下的url.py文件瀏覽器

from django.conf.urls import url
from booktest import views
urlpatterns = [
	url(r'^$',views.index),
]

views.py文件緩存

from django.http import HttpResponse
# Create your views here.
def index(request):
	return  HttpResponse("Hello World!")

啓動django

python manage.py runserver

訪問網址

 

1.3 匹配規則

  第一步:去掉域名和端口號

  第二步:在根目錄下匹配(匹配成功,進入include)

  第三步:去掉根目錄裏面已經匹配成功的,繼續在APP中urls.py匹配(匹配成功,執行對應views.py中的函數)

  第四步:執行view.py中的函數

  匹配的時候,能夠利用正則中的()能夠保留匹配的內容,形如:(\d+)

1.4  urlconf 

#正則表達式非命名組,經過位置參數傳遞給視圖
url(r'^([0-9]+)/$', views.detail, name='detail'),

#正則表達式命名組,經過關鍵字參數傳遞給視圖,本例中關鍵字參數爲id
url(r'^(?P<id>[0-9]+)/$', views.detail, name='detail'),
  • 參數匹配規則:優先使用關鍵字(命名)參數,若是沒有命名參數則使用位置參數
  • 每一個捕獲的參數都做爲一個普通的python字符串傳遞給視圖
  • 性能:urlpatterns中的每一個正則表達式在第一次訪問它們時被編譯,這使得系統至關快
# namespace跟url裏面的name同樣,起名字用於反向解析
url(r'^', include('booktest.urls', namespace='booktest')),

1.5 反向解析(以後在寫)

  • 若是在視圖、模板中使用硬編碼的連接,在urlconf發生改變時,維護是一件很是麻煩的事情
  • 解決:在作連接時,經過指向urlconf的名稱,動態生成連接地址
  • 視圖:使用django.core.urlresolvers.reverse()函數
  • 模板:使用url模板標籤

2. 視圖函數

2.1 基本視圖

  調用,views內對應的函數便可,

2.2 錯誤視圖(404未找到,500服務器未響應,400錯誤來自客戶端)

  Django原生自帶幾個默認視圖用於處理HTTP錯誤

  第一步:項目目錄下,添加templates文件夾

  第二步:settings.py 中添加模板路徑

  第三步:在templates中建立404.html(調試狀態下,看不到這頁面)

  settings.py 設置DEBUG爲False

  設置容許誰請求主機

  

404.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
<h1>找不到,404</h1>
{{ request_path}}}
</body>
</html>

啓動,錯誤的訪問的結果爲:

3. Reqeust對象(接收的對象)

  在django.http模塊中定義了HttpRequest對象的API

3.1 屬性

  下面除非特別說明,屬性都是隻讀的

  path:一個字符串,表示請求的頁面的完整路徑,不包含域名

def index(request):
	return  HttpResponse(request.path)

  

  method:一個字符串,表示請求使用的HTTP方法,經常使用值包括:'GET'、'POST'

  encoding:一個字符串,表示提交的數據的編碼方式

    若是爲None則表示使用瀏覽器的默認設置,通常爲utf-8

    這個屬性是可寫的,能夠經過修改它來修改訪問表單數據使用的編碼,接下來對屬性的任何訪問將使用新的encoding值

  GET:一個相似於字典的對象,包含get請求方式的全部參數

  POST:一個相似於字典的對象,包含post請求方式的全部參數

  FILES:一個相似於字典的對象,包含全部的上傳文件

  COOKIES:一個標準的Python字典,包含全部的cookie,鍵和值都爲字符串

  session:一個既可讀又可寫的相似於字典的對象,表示當前的會話,只有當Django 啓用會話的支持時纔可用,詳細內容見「狀態保持」

  這些屬性的用法相似

from django.http import HttpResponse
# Create your views here.
def index(request):
	return HttpResponse(
		# request.path,
		# request.method,
		# request.encoding,
		request.GET,
		# request.POST,
		# request.FILES,
		# request.COOKIES,
		# request.session,
	)

  

3.2  相似字典對象(QueryDict對象)

  字典:鍵值對,鍵不能相同

  QueryDict:鍵值對,鍵能相同,若是同一鍵有多個值,獲取最後一個值

  get():根據鍵獲取值,類字典

dict.get('鍵',default)
#或簡寫爲
dict['鍵']

  getlist():根據鍵獲取多個值

#將鍵的值以列表返回,能夠獲取一個鍵的多個值
dict.getlist('鍵',default)

3.3 GET屬性 

  • QueryDict類型的對象
  • 包含get請求方式的全部參數
  • 與url請求地址中的參數對應,位於?後面
  • 參數的格式是鍵值對,如key1=value1
  • 多個參數之間,使用&鏈接,如key1=value1&key2=value2
  • 鍵是開發人員定下來的,值是可變的

對應三種視圖getTest1用於定義連接,getTest2用於接收一鍵一值,getTest3用於接收一鍵多值

views.py

from django.shortcuts import render

# Create your views here.
# 展現連接的頁面
def getTest1(request):
	return render(request, 'booktest/getTest1.html')


# 接收一鍵一值的狀況
def getTest2(request):
	# request.GET.get('a')
	# 根據鍵接收值
	a1 = request.GET['a']
	b1 = request.GET['b']
	c1 = request.GET['c']
	# 構造上下文
	context = {'a':a1,'b':b1,'c':c1}
	# 向模板傳遞上下文,並渲染
	return render(request, 'booktest/getTest2.html', context=context)


# 接收一鍵多值的狀況
def getTest3(request):
	# 獲得最後一個
	a1 = request.GET['a']
	# 獲得多個
	a2 = request.GET.getlist('a')
	c1 = request.GET['c']
	contest = {'a':a1,'a1':a2,'c':c1}
	return render(request, 'booktest/getTest3.html',context=contest)

  

配置urls.py(APP裏面的)

from django.conf.urls import url
from booktest import views
urlpatterns = [
	url(r'^getTest1/$',views.getTest1),
	url(r'^getTest2/$',views.getTest2),
	url(r'^getTest3/$',views.getTest3),
]

  

配置模板

getTest1.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>test1</title>
</head>
<body>
一鍵一值:<a href="/booktest/getTest2/?a=1&b=2&c=3">test2</a>
<hr>
一鍵多值:<a href="/booktest/getTest3/?a=1&a=2&c=3">test3</a>
</body>
</html>

  效果:

getTest2.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>test2</title>
</head>
<body>
a:{{a}}
<hr>
b:{{b}}
<hr>
c:{{c}}
</body>
</html>

  效果

getTest3.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>test3</title>
</head>
<body>
a:{{a}}
<br>
a1:{{a1}}
<br>
a2:{%for item in a1 %}
{{ item }}
{% endfor %}
<br>
c:{{c}}

</body>
</html>

  效果

3.4 POST屬性

  • QueryDict類型的對象
  • 包含post請求方式的全部參數
  • 與form表單中的控件對應
  • 問:表單中哪些控件會被提交?
  • 答:控件要有name屬性,則name屬性的值爲鍵,value屬性的值爲鍵,構成鍵值對提交
    • 對於checkbox控件,name屬性同樣爲一組,當控件被選中後會被提交,存在一鍵多值的狀況
  • 鍵是開發人員定下來的,值是可變的

使用表單提交,註釋掉settings.py中的中間件crsf

 views.py

from django.shortcuts import render

# Create your views here.

# 提交表單
def postTest1(request):
	return render(request,'booktest/postTest1.html')
# 展現提交的表單內容
def postTest2(request):
	# 表單的name做爲鍵,value做爲值傳遞過來
	uname = request.POST['uname']
	upwd = request.POST['upwd']
	ugender = request.POST['ugender']
	uhobby = request.POST.getlist('uhobby')
	context = {'uname': uname, 'upwd': upwd, 'ugender': ugender, 'uhobby': uhobby}
	return render(request,'booktest/postTest2.html',context=context)

  

配置urls.py(APP裏面的)

from django.conf.urls import url
from booktest import views
urlpatterns = [
	# url(r'^getTest1/$',views.getTest1),
	# url(r'^getTest2/$',views.getTest2),
	# url(r'^getTest3/$',views.getTest3),
	url(r'^postTest1/$',views.postTest1),
	url(r'^postTest2/$',views.postTest2),
]

  

配置模板

postTest1.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>postTest1</title>
</head>
<body>
<form action="/booktest/postTest2/" method="post">
    姓名:<input type="text" name="uname"/><br>
    密碼:<input type="password" name="upwd"/><br>
    性別:<input type="radio" name="ugender" value="1"/>男
    <input type="radio" name="ugender" value="0"/>女<br>
    愛好:<input type="checkbox" name="uhobby" value="玩LOL"/>玩LOL
    <input type="checkbox" name="uhobby" value="跳樓"/>跳樓
    <input type="checkbox" name="uhobby" value="喝酒"/>喝酒
    <input type="checkbox" name="uhobby" value="登山"/>登山<br>
    <input type="submit" value="提交"/>
</form>
</body>
</html>

  效果:

postTest2.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>postTest2</title>
</head>
<body>
{{ uname }}<br>
{{ upwd }}<br>
{{ ugender }}<br>
{{ uhobby }}
</body>
</html>

  效果:

4. Response對象(發送的對象)

4.1 屬性

  • content:表示返回的內容,字符串類型
  • charset:表示response採用的編碼字符集,字符串類型
  • status_code:響應的HTTP響應狀態碼
  • content-type:指定輸出的MIME類型(解析方式)

4.2 方法

 

  • init :使用頁內容實例化HttpResponse對象
  • write(content):以文件的方式寫
  • flush():以文件的方式輸出緩存區
  • set_cookie(key, value='', max_age=None, expires=None):設置Cookie
    • key、value都是字符串類型
    • max_age是一個整數,表示在指定秒數後過時
    • expires是一個datetime或timedelta對象,會話將在這個指定的日期/時間過時,注意datetime和timedelta值只有在使用PickleSerializer時纔可序列化
    • max_age與expires二選一
    • 若是不指定過時時間,則兩個星期後過時

 

views.py

 

from django.shortcuts import render
from django.http import HttpResponse
from datetime import *

# Create your views here.
def cookieTest(request):
	response = HttpResponse()
	cookie = request.COOKIES
	if 't1' in cookie:
		response.write(cookie['t1'])
	response.set_cookie('t1','abcaaa')
	return response

urls.py

 

 

url(r'^cookieTest/$',views.cookieTest),

 

  效果:

4.3 重定向

  通常做爲:登陸成功後,轉向新的頁面

  HttpResponseRedirect類繼承於HttpResponse

views.py

from django.shortcuts import render,redirect
from django.http import HttpResponse,HttpResponseRedirect



# Create your views here.
def redTest1(request):
	# return HttpResponseRedirect('/booktest/redTest2/')
	# 跟上面功能一致,也用於重定向(簡寫)
	return redirect('/booktest/redTest2/')
# 轉向來的頁面
def redTest2(request):
	return HttpResponse("這是轉向來的頁面")

urls.py

url(r'^redTest1/$',views.redTest1),
	url(r'^redTest2/$',views.redTest2),

 效果:訪問:http://127.0.0.1:8000/booktest/redTest1/

 自動跳轉,效果

 

4.4 狀態保持

  • http協議是無狀態的:每次請求都是一次新的請求,不會記得以前通訊的狀態
  • 客戶端與服務器端的一次通訊,就是一次會話
  • 實現狀態保持的方式:在客戶端或服務器端存儲與會話有關的數據
  • 存儲方式包括cookie、session,會話通常指session對象
  • 使用cookie,全部數據存儲在客戶端,注意不要存儲敏感信息
  • 推薦使用sesison方式,全部數據存儲在服務器端,在客戶端cookie中存儲session_id
  • 狀態保持的目的是在一段時間內跟蹤請求者的狀態,能夠實現跨頁面訪問當前請求者的數據
  • 注意:不一樣的請求者之間不會共享這個數據,與請求者一一對應

Django默認就啓用Session,不用就去settings.py中禁用

使用Session(會存到數據庫中去)

  • 啓用會話後,每一個HttpRequest對象將具備一個session屬性,它是一個類字典對象
  • get(key, default=None):根據鍵獲取會話的值
  • clear():清除全部會話
  • flush():刪除當前的會話數據並刪除會話的Cookie
  • del request.session['member_id']:刪除會話

views.py

from django.shortcuts import render, redirect
from django.http import HttpResponse, HttpResponseRedirect


# Create your views here.
# 第一個登陸顯示頁面
def session1(request):
	# 鍵不存在,設置默認值
	uname = request.session.get('myname','未登陸')
	context = {'uname': uname}
	return render(request, 'booktest/session1.html', context=context)

# 登陸表單提交階段
def session2(request):
	return render(request, 'booktest/session2.html')

# 刪除session,退出
def session3(request):
	del request.session['myname']
	return redirect('/booktest/session1/')

def session2_handle(request):
	uname = request.POST['uname']
	# session對象(字典) 往session對象中寫對象
	request.session['myname'] = uname
	# 重定向,顯示登陸的頁面
	return redirect('/booktest/session1/')

urls.py

url(r'^session1/$',views.session1),
	url(r'^session2/$',views.session2),
	url(r'^session2_handle/$',views.session2_handle),
	url(r'^session3/$',views.session3),

  

session1.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>login</title>
</head>
<body>
<h1>你好:{{ uname }}</h1>
<br>
<a href="/booktest/session2/">登陸</a>
<br>
<a href="/booktest/session3/">退出</a>
</body>
</html>

  效果:

 

 

 

 

 

 

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>表單</title>
</head>
<body>
<form action="/booktest/session2_handle/" method="post">
    <input type="text" name="uname">
    <input type="submit" name="登陸">
</form>
</body>
</html>

 

 效果:

 

由於Session須要存到數據庫:須要進行數據遷移-------這個須要運行前先遷移

settings.py(能夠用已經遷移過的數據庫、表)

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'test2',
        'USER':'root',
        'PASSWORD':'',
        'HOST':'localhost',
        'POST':'3306',
    }
}

  

提交表單後效果

點擊退出後的效果(使用默認值,清楚session)

4.5 會話

會話過時時間

  • set_expiry(value):設置會話的超時時間
  • 若是沒有指定,則兩個星期後過時
  • 若是value是一個整數,會話將在values秒沒有活動後過時
  • 若果value是一個imedelta對象,會話將在當前時間加上這個指定的日期/時間過時
  • 若是value爲0,那麼用戶會話的Cookie將在用戶的瀏覽器關閉時過時
  • 若是value爲None,那麼會話永不過時
  • 修改視圖中session2_handle函數,查看效果
def session2_handle(request):
	uname = request.POST['uname']
	# session對象(字典) 往session對象中寫對象
	request.session['myname'] = uname
	# 設置會話過時時間
	request.session.set_expiry(0)
	# 重定向,顯示登陸的頁面
	return redirect('/booktest/session1/')  

存儲session

數據庫中的session

base64解碼--session_data

  • 使用存儲會話的方式,能夠使用settings.py的SESSION_ENGINE項指定
  • 基於數據庫的會話:這是django默認的會話存儲方式,須要添加django.contrib.sessions到的INSTALLED_APPS設置中,運行manage.py migrate在數據庫中安裝會話表,可顯示指定爲
SESSION_ENGINE='django.contrib.sessions.backends.db'

  存在緩存

SESSION_ENGINE='django.contrib.sessions.backends.cache'

  存在數據庫+緩存

SESSION_ENGINE='django.contrib.sessions.backends.cached_db'

流程

相關文章
相關標籤/搜索