Django(二) 視圖View知識點
1.url匹配的過程
2.定義視圖函數
request參數必須有。是一個HttpRequest類型的對象。視圖必須返回HttpResponse對象,HttpResponse中的參數內容會顯示在瀏覽器的頁面上。也可能重定向redirect,還可以返回json數據。
from django.shortcuts import render
from django.http import HttpResponse
from django.template import loader,RequestContext
# 視圖調用模板
'''
1.找到模板
2.定義上下文
3.渲染模板
'''
def my_render(request, template_path, context_dict={}):
# 使用模板文件
# 1.加載模板文件,模板對象
temp = loader.get_template(template_path)
# 2.定義模板上下文:給模板傳遞數據
context = RequestContext(request, context_dict)
# 3.模板渲染:產生標準的Html內容
res_html = temp.render(context)
# 4.返回瀏覽器
return HttpResponse(res_html)
# http://127.0.0.1:8000/index
def index(request):
# 進行處理,和M和T進行交互,content是給前端傳的參數
return my_render(request, 'booktest/index.html',{'content':'hello word', 'list':list(range(1,10))})
# http://127.0.0.1:8000/index2
def index2(request):
return HttpResponse('老鐵666')
3.進行url配置,建立url地址和視圖的對應關係
在應用中定義URLconf,booktest/應用下創建urls.py文件
from django.conf.urls import url
from booktest import views
# 通過url函數設置url路由配置項
urlpatterns = [
# 建立/index和視圖index之間的關係
url(r'^index$', views.index),
url(r'^index2$', views.index2),
]
將應用包含到項目中:打開test1/urls.py文件,爲urlpatterns列表增加項如下:
from django.conf.urls import include, url
from django.contrib import admin
# 項目的urls文件
urlpatterns = [
# 配置項目
url(r'^admin/', include(admin.site.urls)),
# 包含booktest應用中的urls文件
url(r'^', include('booktest.urls')),
]
4.創建模版
爲應用booktest下的視圖index創建模板index.html,目錄結構如下圖:
設置查找模板的路徑:打開test1/settings.py文件,設置TEMPLATES的DIRS值
# 設置模板路徑
'DIRS': [os.path.join(BASE_DIR, 'templates')],
設置自動加載 修改test1/init.py
import pymysql
pymysql.install_as_MySQLdb()
5.定義模板
修改templtes/booktest/index.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板文件</title>
</head>
<body>
<h1>這是一個模板</h1>
使用模板變量<br/>
{{ content }}
<br/>
{{ list }}
</body>
</html>
6.訪問
HttpReqeust對象
服務器接收到http協議的請求後,會根據報文創建HttpRequest對象,這個對象不需要我們創建,直接使用服務器構造好的對象就可以。視圖的第一個參數必須是HttpRequest對象,在django.http模塊中定義了HttpRequest對象的API。
POST:提交的參數請求頭。數據安全性要求比較高的時候使用post.
GET:提交的參數在url中。
屬性
下面除非特別說明,屬性都是隻讀的。
• path:一個字符串,表示請求的頁面的完整路徑,不包含域名和參數部分。
• method:一個字符串,表示請求使用的HTTP方法,常用值包括:‘GET’、‘POST’。
• 在瀏覽器中給出地址發出請求採用get方式,如超鏈接。
• 在瀏覽器中點擊表單的提交按鈕發起請求,如果表單的method設置爲post則爲post請求。
• encoding:一個字符串,表示提交的數據的編碼方式。
• 如果爲None則表示使用瀏覽器的默認設置,一般爲utf-8。
• 這個屬性是可寫的,可以通過修改它來修改訪問表單數據使用的編碼,接下來對屬性的任何訪問將使用新的encoding值。
• GET:QueryDict類型對象,類似於字典,包含get請求方式的所有參數。
• POST:QueryDict類型對象,類似於字典,包含post請求方式的所有參數。
• FILES:一個類似於字典的對象,包含所有的上傳文件。
• COOKIES:一個標準的Python字典,包含所有的cookie,鍵和值都爲字符串。
• session:一個既可讀又可寫的類似於字典的對象,表示當前的會話,只有當Django 啓用會話的支持時纔可用,詳細內容見"狀態保持"。
捕獲url參數
進行url匹配時,把所需要的捕獲的部分設置成一個正則表達式組,這樣django框架就會自動把匹配成功後相應組的內容作爲參數傳遞給視圖函數。
- 位置參數
位置參數,參數名可以隨意指定
# 捕獲url參數:位置參數
url(r'^showarg(\d+)$', views.show_arg),
- 關鍵字參數:在位置參數的基礎上給正則表達式組命名即可。
?P<組名>
關鍵字參數,視圖中參數名必須和正則表達式組名一致.
# 捕獲url參數:關鍵字參數
url(r'^showarg(?P<num>\d+)$', views.show_arg),
定義視圖
def show_arg(request, num):
return HttpResponse(num)
form表單示例
1)打開booktest/views.py文件,創建視圖
def login(request):
'''顯示登錄頁面'''
return render(request, 'booktest/login.html')
def login_check(request):
'''登錄校驗視圖'''
# request.POST 保存的是post方式提交的參數QueryDict
# request.GET 保存是get方式提交的參數
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'smart' and password == '123':
# 用戶名密碼正確,跳轉到首頁
response = redirect('/index')
return response
else:
# 用戶名或密碼錯誤,跳轉到登錄頁面
return redirect('/login')
2)打開booktest/urls.py文件,配置url。
# 顯示登錄頁面
url(r'^login$', views.login),
# 用戶登錄校驗
url(r'^login_check$', views.login_check),
3)修改templates/booktest目錄下的login.html,添加代碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登錄頁面</title>
</head>
<body>
<form method="post" action="/login_check">
用戶名:<input type="text" name="username" value="{{ username }}"><br/>
密碼:<input type="password" name="password"><br/>
<input type="submit" value="登錄">
</form>
</body>
</html>
解釋:使用form表單請求時,method方式爲post則會發起post方式的請求,需要使用HttpRequest對象的POST屬性接收參數,POST屬性是一個QueryDict類型的對象。
表單form如何提交參數的?
答:表單控件name屬性的值作爲鍵,value屬性的值爲值,構成鍵值對提交。
• 如果表單控件沒有name屬性則不提交。
• 對於checkbox控件,name屬性的值相同爲一組,被選中的項會被提交,出現一鍵多值的情況。
• 鍵是表單控件name屬性的值,是由開發人員編寫的。
• 值是用戶填寫或選擇的。
4)運行服務器。
HttpResponse對象
視圖在接收請求並處理後,必須返回HttpResponse對象或子對象。在django.http模塊中定義了HttpResponse對象的API。HttpRequest對象由Django創建,HttpResponse對象由開發人員創建。
JsonResponse
在瀏覽器中使用javascript發起ajax請求時,返回json格式的數據,此處以jquery的get()方法爲例。類JsonResponse繼承自HttpResponse對象,被定義在django.http模塊中,創建對象時接收字典作爲參數。
JsonResponse對象的content-type爲'application/json'
重定向 HttpResponseRedirect
Django中提供了HttpResponseRedirect對象實現重定向功能,這個類繼承自HttpResponse,被定義在django.http模塊中,返回的狀態碼爲302
示例
1)在booktest/views.py文件中定義視圖red1,代碼如下:
from django.http import HttpResponseRedirect
...
# 定義重定義向視圖,轉向首頁
def index(request):
return HttpResponseRedirect('/login')
重定向簡寫函數redirect
在django.shortcuts模塊中爲重定向類提供了簡寫函數redirect。
1)修改booktest/views.py文件中red1視圖,代碼如下:
from django.shortcuts import redirect
...
def index(request):
return redirect('/login')
Cookie
Cookie的特點
• Cookie以鍵值對的格式進行信息的存儲。
• Cookie基於域名安全,不同域名的Cookie是不能互相訪問的,如訪問itcast.cn時向瀏覽器中寫了Cookie信息,使用同一瀏覽器訪問baidu.com時,無法訪問到itcast.cn寫的Cookie信息。
• 當瀏覽器請求某網站時,會將瀏覽器存儲的跟網站相關的所有Cookie信息提交給網站服務器。
• cookie是有過期時間的,如果不指定,默認關閉瀏覽器之後cookie就會過期。
• cookie是由服務器生成,存儲在瀏覽器端的一小段文本信息。
典型應用:記住用戶名,網站的廣告推送。
設置Cookie
1)打開booktest/views.py文件,創建視圖set_cookie
def set_cookie(request):
'''設置cookie信息'''
response = HttpResponse('設置cookie')
# 設置一個cookie信息,名字爲num, 值爲1,保存時間2周
response.set_cookie('num', 1, max_age=14*24*3600)
# 返回response
return response
2)打開booktest/urls.py文件,配置url。
url(r'^set_cookie$',views.set_cookie),
3)在瀏覽器輸入如下網址。
http://127.0.0.1:8000/set_cookie/
讀取Cookie
Cookie信息被包含在請求頭中,使用request對象的COOKIES屬性訪問。
1)打開booktest/views.py文件,創建視圖get_cookie
def get_cookie(request):
'''獲取cookie的信息'''
# 取出cookie num的值
num = request.COOKIES['num']
return HttpResponse(num)
2)打開booktest/urls.py文件,配置url。
url(r'^get_cookie$',views.get_cookie),
3)在瀏覽器輸入如下網址。
http://127.0.0.1:8000/get_cookie/
Session
session的特點
• session是以鍵值對進行存儲的
• session依賴於cookie。唯一的標識碼保存在sessionid cookie中
• session也是有過期時間,如果不指定,默認兩週就會過期
• session存儲在服務器端
典型應用:對於敏感、重要的信息,建議要儲在服務器端,不能存儲在瀏覽器中,如用戶名、餘額、等級、驗證碼等信息。
依賴於Cookie
所有請求者的Session都會存儲在服務器中,服務器如何區分請求者和Session數據的對應關係呢?
答:在使用Session後,會在Cookie中存儲一個sessionid的數據,每次請求時瀏覽器都會將這個數據發給服務器,服務器在接收到sessionid後,會根據這個值找出這個請求者的Session。
結果:如果想使用Session,瀏覽器必須支持Cookie,否則就無法使用Session了。
存儲Session時,鍵與Cookie中的sessionid相同,值是開發人員設置的鍵值對信息,進行了base64編碼,過期時間由開發人員設置。
啓用Session
Django項目默認啓用Session。
存儲方式
打開test3/settings.py文件,設置SESSION_ENGINE項指定Session數據存儲的方式,可以存儲在數據庫、緩存、Redis等。
1)存儲在數據庫中,如下設置可以寫,也可以不寫,這是默認存儲方式。
SESSION_ENGINE='django.contrib.sessions.backends.db'
2)存儲在緩存中:存儲在本機內存中,如果丟失則不能找回,比數據庫的方式讀寫更快。
SESSION_ENGINE='django.contrib.sessions.backends.cache'
3)混合存儲:優先從本機內存中存取,如果沒有則從數據庫中存取。
SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
4)如果存儲在數據庫中,需要在項INSTALLED_APPS中安裝Session應用。
5)遷移後會在數據庫中創建出存儲Session的表。
6)表結構如下圖。
由表結構可知,操作Session包括三個數據:鍵,值,過期時間。
設置session
1)打開booktest/views.py文件,創建視圖set_session,代碼如下:
def set_session(request):
'''設置session'''
request.session['username'] = 'smart'
request.session['age'] = 18
# request.session.set_expiry(5)
return HttpResponse('設置session')
2)打開booktest/urls.py文件,配置url。
url(r'^set_session$',views.set_session),
3)運行服務器,打開瀏覽器請求如下網址。
http://127.0.0.1:8000/set_session/
4)瀏覽效果如下圖,在"開發者工具"中可以查看到響應頭中創建了Cookie,裏面有個鍵爲sessionid。
讀取session
1)打開booktest/views.py文件,修改get_session視圖如下:
def get_session(request):
'''獲取session'''
username = request.session['username']
age = request.session['age']
return HttpResponse(username+':'+str(age))
2)打開booktest/urls.py文件,配置url。
url(r'^get_session$',views.get_session),
3)運行服務器,打開瀏覽器請求如下網址。
http://127.0.0.1:8000/get_session/
4)刷新瀏覽器效果如下圖。
刪除Session
1)打開booktest/views.py文件,修改clear_session視圖如下
def clear_session(request):
'''清除session信息'''
request.session.clear()
return HttpResponse('清除成功')
2)刷新瀏覽器,在數據庫命令行中查詢,base64解碼後如下圖。
使用Redis存儲Session
會話還支持文件、純cookie、Memcached、Redis等方式存儲,下面演示使用redis存儲。
1)安裝包。
pip install django-redis-sessions==0.5.6
2)修改test3/settings文件,增加如下項:
SESSION_ENGINE = 'redis_sessions.session'
SESSION_REDIS_HOST = 'localhost'
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DB = 2
SESSION_REDIS_PASSWORD = ''
SESSION_REDIS_PREFIX = 'session'
3)打開booktest/views.py文件,修改session_test視圖如下:
def session_test(request):
request.session['h1']='hello'
return HttpResponse('ok')
4)管理redis的命令,需要保證redis服務被開啓。
查看:ps ajx|grep redis
啓動:sudo service redis start
停止:sudo service redis stop
使用客戶端連接服務器:redis-cli
切換數據庫:select 2
查看所有的鍵:keys *
獲取指定鍵的值:get name
5)刷新瀏覽器,在redis客戶端中查看數據如下。
Session共享
1. 基於Nginx的ip_hash負載均衡
這個方案實現最爲簡單,只要hash屬性是均勻的,多臺web服務器的負載就是均衡的,安全性高,缺點:用戶瀏覽器的IP地址hash以後滿足單調性。會可能造成資源的分配不均衡,負載均衡就達不到到目的。有的服務器負載過重,有的服務器負載過輕,顯然沒有充分利用資源。
2. 基於數據庫的Session共享
首選當然是大名鼎鼎的Mysql數據庫,並且建議使用內存表Heap,提高session操作的讀寫效率。這個方案的實用性比較強,相信大家普遍在使用,它的缺點在於session的併發讀寫能力取決於Mysql數據庫的性能,同時需要自己實現session淘汰邏輯,以便定時從數據表中更新、刪除 session記錄,當併發過高時容易出現表鎖,雖然我們可以選擇行級鎖的表引擎,但不得不否認使用數據庫存儲Session還是有些殺雞用牛刀的架勢。
3. 將信息放到cookie放在客戶端
session存在服務器端,會對服務器產生壓力。如果將信息保存到cookie中,減輕了服務器的壓力,同時每個客戶端的壓力也很小。因爲只保存自己的信息。這種方式在實際的開發中廣泛的採用。
缺點:cookie可以被禁用,cookie要隨着瀏覽器傳遞,增大了傳輸的內容,cookie大小有限制。
4. 基於Redis做緩存session的統一緩存
其實就是把每次用戶的請求的時候生成的sessionID給放到Redis的服務器上。然後在基於Redis的特性進行設置一個失效時間的機制,這樣就能保證用戶在我們設置的Redis中的session失效時間內,都不需要進行再次登錄。
ajax
可模擬任何請求方式向後端發送請求
$.ajax({
url:'地址',
type:'GET',
data:{...},
success:function(arg){
console.log(arg);
}
})