Python後臺開發(第三章: Django高階)
Python後臺開發(第三章: Django高階)
- 1 Cookie
- 2 Session
- 3 Session和Cookie的區別
- 4 Redis資料庫
- 5 表單接收與提交
- 6 csrf跨域攻擊
- 7 模型類多表操作
- 8 中介軟體Middleware應用
- 8.1 概念
- 8.2 原理
- 8.3 中介軟體的註冊
- 8.4 方法詳解
- 8.4.1 init
- 8.4.2 process_request(self,request) 常用
- 8.4.3 process_view(self,request,view_func,view_args,view_kwargs)
- 8.4.4 process_template_response(self,request,response)
- 8.4.5 process_response(self,request,response)
- 8.4.6 process_exception(self,request,exception)
- 8.5 使用場景
- 9 admin後臺管理
- 10 專案淺析
1 Cookie
1.1 Cookie機制
在程式中,會話跟蹤是很重要的事情。理論上,一個使用者的所有請求操作都應該屬於同一個會話,而另一個使用者的所有請求操作則應該屬於另一個會話,二者不能混淆。例如,使用者A在超市購買的任何商品都應該放在A的購物車內,不論是使用者A什麼時間購買的,這都是屬於同一個會話的,不能放入使用者B或使用者C的購物車內,這不屬於同一個會話。
而Web應用程式是使用HTTP協議傳輸資料的。HTTP協議是無狀態的協議。一旦資料交換完畢,客戶端與伺服器端的連線就會關閉,再次交換資料需要建立新的連線。這就意味著伺服器無法從連線上跟蹤會話。即使用者A購買了一件商品放入購物車內,當再次購買商品時伺服器已經無法判斷該購買行為是屬於使用者A的會話還是使用者B的會話了。要跟蹤該會話,必須引入一種機制。
Cookie就是這樣的一種機制。它可以彌補HTTP協議無狀態的不足。在Session出現之前,基本上所有的網站都採用Cookie來跟蹤會話Cookie通過在客戶端記錄資訊確定使用者身份。
1.2 什麼是Cookie
- cookie是儲存在使用者瀏覽器端的鍵值對
- Cookie是由伺服器生成,儲存在瀏覽器中的鍵值對資料
- 每個域名的Cookie相互獨立
- 瀏覽器訪問域名為A的url地址,會把A域名下的Cookie一起傳遞到伺服器
- Cookie可以設定過期時間,預設為None,即關閉當前瀏覽器,Cookie立即清除.
- 儲存站點的使用者資料.
1.3 Cookie原理
Cookie實際上是一小段的文字資訊。客戶端請求伺服器,如果伺服器需要記錄該使用者狀態,就使用response向客戶端瀏覽器頒發一個Cookie。客戶端瀏覽器會把Cookie儲存起來。當瀏覽器再請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給伺服器。伺服器檢查該Cookie,以此來辨認使用者狀態。伺服器還可以根據需要修改Cookie的內容。
1.4 Cookie屬性
1.4.1 屬性表
屬性 | 說明 |
---|---|
set_cookie(常用) | 設定Cookie的值 max_age: 預設為None |
COOKIES.get(常用) | 獲取Cookie的值 |
String name | 該Cookie的名稱。Cookie一旦建立,名稱便不可更改 |
Object value | 該Cookie的值。如果值為Unicode字元,需要為字元編碼。如果值為二進位制資料,則需要使用BASE64編碼 |
int maxAge | 該Cookie失效的時間,單位秒。如果為正數,則該Cookie在maxAge秒之後失效。如果為負數,該Cookie為臨時Cookie,關閉瀏覽器即失效,瀏覽器也不會以任何形式儲存該Cookie。如果為0,表示刪除該Cookie。預設為–1 |
boolean secure | 該Cookie是否僅被使用安全協議傳輸。安全協議。安全協議有HTTPS,SSL等,在網路上傳輸資料之前先將資料加密。預設為false |
String path | 該Cookie的使用路徑。如果設定為“/sessionWeb/”,則只有contextPath為“/sessionWeb”的程式可以訪問該Cookie。如果設定為“/”,則本域名下contextPath都可以訪問該Cookie。注意最後一個字元必須為“/” |
String domain | 可以訪問該Cookie的域名。如果設定為“.google.com”,則所有以“google.com”結尾的域名都可以訪問該Cookie。注意第一個字元必須為“.” |
String comment | 該Cookie的用處說明。瀏覽器顯示Cookie資訊的時候顯示該說明 |
int version | 該Cookie使用的版本號。0表示遵循Netscape的Cookie規範,1表示遵循W3C的RFC 2109規範 |
1.4.2 程式碼例項
1.4.2.1 set_cookie
- url配置
re_path('set_cookie/(.+)/(.+)',views.set_cookie_handler,name='set_cookie')
- views配置
def set_cookie_handler(request,key,value):
response = HttpResponse()
#max_age=60\*60 表示Cookie的有效時間3600秒,即1小時
response.set_cookie(key,value,max_age= 60 * 60)
return response
1.4.2.2 COOKIES.get
- url配置
re_path('get_cookie/(.+)',views.get_cookie_handler,name='get_cookie')
- views配置
def get_cookie_handler(request,key):
value = request.COOKIES.get(key)
return HttpResponse(value)
注:在測試cookie之前,需要先對Django專案執行遷移,才可以在資料庫中得到對應的操作表。
1.4.3 Cookie的刪除和修改
- Cookie並不提供修改、刪除操作。如果要修改某個Cookie,只需要新建一個同名的Cookie,新增到response中覆蓋原來的Cookie。
- 如果要刪除某個Cookie,只需要新建一個同名的Cookie,並將maxAge設定為0,並新增到response中覆原來的Cookie。注意是0而不是負數。負數代表其他的意義。
- 注意:修改、刪除Cookie時,新建的Cookie除value、maxAge之外的所有屬性,例如name、path、domain等,都要與原Cookie完全一樣。否則,瀏覽器將視為兩個不同的Cookie不予覆蓋,導致修改、刪除失敗。
1.4.4 Cookie的域名
- Cookie是不可跨域名的。域名www.google.com頒發的Cookie不會被提交到域名www.baidu.com去。這是由Cookie的隱私安全機制決定的。隱私安全機制能夠禁止網站非法獲取其他網站的Cookie。
- 正常情況下,同一個一級域名下的兩個二級域名如www.helloweenvsfei.com和images.helloweenvsfei.com也不能互動使用Cookie,因為二者的域名並不嚴格相同。如果想所有helloweenvsfei.com名下的二級域名都可以使用該Cookie,需要設定Cookie的domain引數,例如:
Cookie cookie = new Cookie("time","20080808");
// 新建Cookie cookie.setDomain(".helloweenvsfei.com");
// 設定域名 cookie.setPath("/");
// 設定路徑 cookie.setMaxAge(Integer.MAX_VALUE);
// 設定有效期 response.addCookie(cookie);
// 輸出到客戶端
- 可以修改本機C:\WINDOWS\system32\drivers\etc下的hosts檔案來配置多個臨時域名,然後使用setCookie.jsp程式來設定跨域名Cookie驗證domain屬性。
- 注意:domain引數必須以點(".")開始。另外,name相同但domain不同的兩個Cookie是兩個不同的Cookie。如果想要兩個域名完全不同的網站共有Cookie,可以生成兩個Cookie,domain屬性分別為兩個域名,輸出到客戶端。
1.4.5 Cookie的安全性
- Cookie是儲存在客戶端,即瀏覽器的,所有具有不安全性
- 對於敏感的資料,應該加密,或者儲存在服務端
2 Session
2.1 Session機制
除了使用Cookie,Web應用程式中還經常使用Session來記錄客戶端狀態。Session是伺服器端使用的一種記錄客戶端狀態的機制,使用上比Cookie簡單一些,相應的也增加了伺服器的儲存壓力。
2.2 什麼是Session
- session是儲存在伺服器端的鍵值對。
- Session基於Cookie的。
- Session把敏感的資料以加密的方式儲存在伺服器。
- Session預設的過期時間是兩週,如果自己設定了過期時間,這樣自己設定的優先順序就會高於預設的
- Session是另一種記錄客戶狀態的機制,不同的是Cookie儲存在客戶端瀏覽器中,而Session儲存在伺服器上。客戶端瀏覽器訪問伺服器的時候,伺服器把客戶端資訊以某種形式記錄在伺服器上。這就是Session。客戶端瀏覽器再次訪問時只需要從該Session中查詢該客戶的狀態就可以了。如果說Cookie機制是通過檢查客戶身上的“通行證”來確定客戶身份的話,那麼Session機制就是通過檢查伺服器上的“客戶明細表”來確認客戶身份。Session相當於程式在伺服器上建立的一份客戶檔案,客戶來訪的時候只需要查詢客戶檔案表就可以了。
2.3 Session原理
2.4 Session常用方法
屬性 | 說明 |
---|---|
session[key] = value | 設定Session的值 設定過期時間,預設為2周: session.set_expiry(60*60) |
session.get(key) | 獲取Session的值,如果沒有這個key,返回None |
flush() | 刪除表資料 |
clear() | 清空sessionId對應的資料 |
2.5 程式碼例項
2.5.1 設定
- url配置
re_path('set_session/(.+)/(.+)',views.set_session_handler,name='set_session'),
- views配置
def set_session_handler(request,key,value):
request.session[key] = value
#設定過期時間
request.session.set_expiry(60 * 60)
return HttpResponse('設定成功')
2.5.2 獲取
1.url配置
re_path('get_session/(.+)',views.get_session_handler,name='get_session'),
2.views配置
def get_session_handler(request,key):
value = request.session.get(key)
return HttpResponse(value)
2.5.3 刪除
- url配置
path('flush',views.flush_session_handler,name='flush'),
- views配置
def flush_session_handler(request):
request.session.flush()
2.5.4 clear
- url配置
path('clear',views.clear_session_handler,name='clear'),
- views配置
def clear_session_handler(request):
request.session.clear()
return HttpResponse('clear')
2.6 Session—mysql
2.6.1 資料庫資訊配置
專案settings檔案的DATABASES中配置mysql引擎。
DATABASES = { 'default': { 'ENGINE' : 'django.db.backends.mysql', 'HOST': 'localhost',
#一般都是localhost
'PORT': '3306',
#本地mysql服務執行的埠號
'NAME': 'django3',
#本地mysql庫中存在設定的庫
'USER': 'root',
#使用者必須為root
'PASSWORD': '12345',
#cmd下連線mysql資料庫使用的密碼 } }
2.6.2 執行遷移,生成Session表
在終端Terminal 專案目錄下執行資料表更新命令:
python manag.py makemigrations # 生成遷移檔案
python manag.py migrate # 執行遷移
重新整理資料庫,檢視是否生成了django_session表
3 Session和Cookie的區別
- cookie資料存放在客戶的瀏覽器上,session資料放在伺服器上。
- cookie不是很安全,別人可以分析存放在本地的COOKIE並進行COOKIE欺騙 考慮到安全應當使用session。
- session會在一定時間內儲存在伺服器上。當訪問增多,會比較佔用你伺服器的效能 考慮到減輕伺服器效能方面,應當使用COOKIE。
- 單個cookie儲存的資料不能超過4K,很多瀏覽器都限制一個站點最多儲存20個cookie。
- 所以個人建議: 將登陸資訊等重要資訊存放為SESSION 其他資訊如果需要保留,可以放在COOKIE中
4 Redis資料庫
4.1 Redis概述
- 非關係型資料庫
- 資料讀寫的速度快
- 可以儲存的資料量少
- 記憶體資料庫,支援資料的持久化,可以將記憶體中的資料儲存在磁碟中,重啟的時候可以再次載入進行使用。
- Redis不僅僅支援簡單的key-value型別的資料,同時還提供list,set,zset,hash等資料結構的儲存。
4.2 Redis安裝
- 下載課件,找到redis—msi的安裝包,也可在QQ群中下載。
- 點選安裝包,一路next,finish完成安裝。
- cmd下 輸入 redis –cli ,若出現以截圖,說明沒有把redis的資料庫新增到環境變數中
- 得到以下截圖結果,說明安裝成功
4.3 Redis視覺化工具的使用
1.接下來我們來安裝Redis視覺化管理工具Redis Desktop Manager
2.安裝包在課件,qq群內均可下載。
3.安裝參考連結:https://jingyan.baidu.com/article/925f8cb8b92debc0dde05603.html
4.4 環境搭建(模組包的安裝)
pip install redis
pip install django-redis
pip install django-redis-sessions
注:若環境中存在2個Python版本,可使用pip3 進行安裝,mac使用者也可使用brew安裝
4.5 Session—Redis的使用
在settings中配置如下資訊:
SESSION_ENGINE = 'redis_sessions.session' \# 選擇Redis儲存Session
SESSION_REDIS_HOST = 'localhost' \# Redis的主機地址
SESSION_REDIS_PORT = 6379 \# Redis的埠號
SESSION_REDIS_DB = 0 \# 資料庫編號,0-11 SESSION_REDIS_PASSWORD = '' \#
登入Redis的密碼
注:完成配置,執行遷移,專案操作的session資訊會通過使用的redis-session引擎將資訊寫入到Redis資料庫中。
5 表單接收與提交
5.1 表單格式
5.1.1 基礎格式
form標籤 提交地址 action 提交方法 method get post 提交檔案 enctype="multipart/form-data"
例如:
<form action="www.edu.csdn.net" method="post" enctype="multipart/form-data >
5.1.2 input屬性
屬性 | 說明 |
---|---|
text | 文字輸入框 |
password | 密碼輸入框 |
radio | 單選框 |
checkbox | 核取方塊 |
file | 檔案框 |
button | 按鈕 |
submit | 提交 |
reset | 重置 |
5.1.3 下拉框
<select>
<option>選項1</option>
<option>選項2</option>
</select>
5.1.4 大文字
<textarea cols="列數" rows="行數" > </textarea>
5.1.5 表單程式碼例項
<!DOCTYPE html\>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="{% url 'form_post' %}" >
username: <input type="text" name="username" ><br\>
hobby: <input type="checkbox" name="hobby" value="Python">Python
<input type="checkbox" name="hobby" value="Java">Java <br\>
<input type="submit" value="submit">
</form>
</body>
</html>
5.2 請求原理
5.3 Get
5.3.1 提交
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="{% url 'form_post' %}" method="get">
username: <input type="text" name="username" ><br/>
hobby: <input type="checkbox" name="hobby" value="Python">Python
<input type="checkbox" name="hobby" value="Java">Java <br/>
<input type="submit" value="submit">
</form>
</body>
</html>
5.3.2 接收
5.3.2.1 基礎格式
value = request.GET.get([key],[預設值]) values = request.GET.getlist ([key])
5.3.2.2 程式碼例項
1.url配置
path('form_get',views.form_get_handler,name='form_get'),
2.views配置
def form_get_handler(request):
username = request.GET.get('username')
hobbys = request.GET.getlist('hobby')
print('username:',username)
print('hobbys',hobbys)
return HttpResponse('')
5.4 Post
5.4.1 提交
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="{% url 'form_post' %}" method="post">
{% csrf_token %}
username: <input type="text" name="username" ><br/>
hobby: <input type="checkbox" name="hobby" value="Python">Python
<input type="checkbox" name="hobby" value="Java">Java <br/>
<input type="submit" value="submit">
</form>
</body>
</html>
注:Post請求,需要在表單中加入{% csrf_token %},或者取消csrf中介軟體
5.4.2 接收
5.4.2.1 基礎格式
value = request.POST.get([key],[預設值]) values = request.POST.getlist ([key])
5.4.2.2 程式碼例項
1.url配置
path('form_post',views.form_post_handler,name='form_post'),
2.views配置
def form_post_handler(request):
username = request.POST.get('username')
hobbys = request.POST.getlist('hobby')
print('username:',username)
print('hobbys',hobbys)
return HttpResponse('')
6 csrf跨域攻擊
6.1 原理
1.在django的任何post請求,都會在請求之初,給使用者下發一下串用來校驗身份的編碼,並且每次請求不一樣。
2.如果不加csrf_token校驗,會發生csrf錯誤
3.使用django的csrf校驗,{% csrf_token
%}標籤實際上就是在前端的form表單當中生成了一個hidden隱藏域,name為csrfmiddlewaretoken,value是csrf校驗的值
6.2 解決跨域攻擊
- 關閉中介軟體
- 表單加入{% csrf_token %}
6.3 程式碼例項
1.定義表單
2.url
3.檢視檔案, 完成註冊
7 模型類多表操作
7.1 基本原則
- 一對一的表,兩表的屬性實際上完全可以合併成一個表,共用一個主鍵即可;
- 一對多的表,可以設中間關聯表,也可以將關聯表併入“多”這頭;若設獨立關聯表,則可引入“多”這頭的主鍵作為其主鍵,也可另立主鍵並將“一”和“多”兩表的主鍵作為關聯表的外來鍵;
- 多對多的表,則必須通過Django建立管理中間關聯表,關聯表設獨立主鍵,並引入兩個“多”頭的表的主鍵作為關聯表的外來鍵。
- 能用1對1的,就不用1對多;能用1對多的,就不用多對多,往簡單化方向靠;
- 能當屬性處理的,儘量當屬性,而不是當實體處理去另立新表,這樣可使問題簡化。
- 把意義相近聯絡緊密的屬性放在一張表內,而不是拆在多張表中。
7.2 外來鍵種類
關鍵字 | 說明 |
---|---|
ForeignKey | 一對多 定義在多的一端中 |
ManyToManyField | 多對多 定義在任意一方 |
OneToOneField | 一對一 定義在任意一方 |
7.3 外來鍵常用引數
關鍵字 | 說明 |
---|---|
to | 引用的模型類 |
on_delete | 外來鍵約束 on_delete=models.CASCADE 級聯操作(多對一,一的一方刪除,多的一方也刪除) on_delete=models.PROTECT 報異常(被引用的一方不能刪除) on_delete=models.SET_NULL 設定為null(多對一,一的一方刪除,多的一方外來鍵為null) on_delete=models.DO_NOTHING 什麼也不做 |
related_name | 反向引用,如果兩個表間有多種外來鍵關係,需要指明related_name |
7.4 一對一
7.4.1 概念
- 子表從母表中選出一條資料一一對應,母表中選出來一條就少一條,子表不可以再選擇母表中已被選擇的那條資料
- 一般用於某張表的補充,比如使用者基本資訊是一張表,但並非每一個使用者都需要有登入的許可權,不需要記錄使用者名稱和密碼,此時,合理的做法就是新建一張記錄登入資訊的表,與使用者資訊進行一對一的關聯,可以方便的從子表查詢母表資訊或反向查詢
- 當某個物件想擴充套件自另一個物件,那可以再這個物件的主鍵上新增一對一的關係
- 當某個物件想擴充套件自另一個物件,那可以再這個物件的主鍵上新增一對一的關係
7.4.2 程式碼例項
7.4.2.1 模型層的建立
# 通過 OneToOneField 建立一對一的關係
from django.db import models
class StaffInfo(models.Model):
name = models.CharField(max_length=32, null=True)
age = models.CharField(max_length=32, null=True)
class Salary(models.Model):
money = models.CharField(max_length=32, null=True)
staff = models.OneToOneField("StaffInfo")
7.4.2.2 增刪改查
# 增 和普通一樣
models.StaffInfo.objects.create(name="xxx",age=12)models.Salary.objects.create(money=3000, staff_id=2)
#一對一關聯的外來鍵如果新增重複會報錯,也就是說django已經幫我們做好了唯一索引
# 刪 和普通的也是一樣的
models.Salary.objects.filter(staff_id=2).delete()
#也有級聯刪除的問題, 可以通過on_delete 修改值取消級聯刪除改 和普通也一樣
models.Salary.objects.filter(staff_id=2).update(money=2000)
# 查分為正查和反差兩種
# 正查 通過點表中外來鍵名跨表查詢 row.staff.nameres = models.Salary.objects.all()
for row in res:
print(row.money, row.staff.name)
# 反差點關聯表的表明小寫進行跨表查詢 row.salary.money
res = models.StaffInfo.objects.all()
for row in res:
print(row.name, row.salary.money)
7.5 一對多
7.5.1 概念
- 通過外來鍵來進行2張表的關聯操作
- 子表從母表中選出一條資料一一對應,但母表的這條資料還可以被其他子表資料選擇
7.5.2 程式碼例項
7.5.2.1 模型層的建立
from django.db import models
class User1(models.Model):
name = models.CharField(max_length=16,unique=True)
# 使用者名稱
class Forum1(models.Model):
name = models.CharField(max_length=16,unique=True)
# 帖子主題
# 發帖的使用者
userObject = models.ForeignKey( to=User1, on_delete=models.CASCADE)
# ‘一’的一方的類
# 級聯操作
7.5.2.2 新增與查詢
# 新增使用者
user = User1.objects.create(name='name1')
# 新增帖子,引用上面建立的使用者
Forum1.objects.create(name='topic1',userObject=user)
# 得到使用者發的所有帖子 \# 一對多,【多的一方的class名小寫_set】
forum_s = User1.objects.get(id=1).forum1_set.all() print(forum_s)
# 得到帖子傳送者物件
# 多對一,【通過定義的外來鍵欄位引用】
user = Forum1.objects.get(name='topic1').userObject print(user)
'''【結果】
<QuerySet [<Forum1: Forum1 object>]> > User1 object
'''
7.5.2.3 引用關係
注:
M —>表示1對多
M得到引用的:通過M中定義的外來鍵欄位得到
得到被應用的所有M:通過M方的類名_set,返回時QuerySet物件,例如user1.forum1_set.all()
7.5.2.4 多對一的自關聯
使用to = ‘self’ 實現自關聯,推薦使用django來維護一對多的自關聯模型
- model.py
class Area(models.Model):
name = models.CharField(max_length=16,unique=True)
# 地區名字
pArea = models.ForeignKey(to='self',null=True)
# 上一級地區的引用
def __str__(self):
return str(self.name)
- 測試
# area1:北京
area1 = Area.objects.create(name='北京')
# area2:朝陽
area2 = Area(name='朝陽')
# 設定area2的父地區是area1北京
area2.pArea = area1 area2.save()
# area3:豐臺
area3 = Area.objects.create(name='豐臺')
# area1北京的子地區,新增area3豐臺
area1.area_set.add(area3)
area_beijing = Area.objects.get(name='北京')
area_chaoyang = Area.objects.get(name='朝陽')
area_fengtai = Area.objects.get(name='豐臺')
# 列印北京的所有子區域
print(area_beijing.area_set.all())
# 列印朝陽的父區域
print(area_chaoyang.pArea)
'''
【結果】
<QuerySet [<Area: 朝陽>, <Area: 豐臺>]> 北京
'''
7.6 多對多
7.6.1 概念
- 建立.多對多模型關係,Django會自己建立,維護一箇中間表。
- django會自動建立一箇中間表:名稱:【app名】【類名小寫】【類名小寫】
- 新增引用關係方法:add()
- 刪除引用關係方法:remove()
7.6.2 測試
7.6.2.1 模型層的建立
class User2(models.Model):
name = models.CharField(max_length=16,unique=True)
# 使用者名稱
def __str__(self):
return str(self.name)
class Hobby2(models.Model):
name = models.CharField(max_length=16,unique=True)
# 愛好名稱
userobjects = models.ManyToManyField(to=User2)
# 多對多
def __str__(self):
return str(self.name)
7.6.2.2 增刪改查
user1 = User2.objects.create(name='name1')
user2 = User2.objects.create(name='name2')
# 建立3個愛好物件
hobby1 = Hobby2.objects.create(name='早上寫程式碼')
hobby2 = Hobby2.objects.create(name='中午寫程式碼')
hobby3 = Hobby2.objects.create(name='晚上寫程式碼')
# 通過使用者,新增引用
user1.hobby2_set.add(hobby1)
user1.hobby2_set.add(hobby2)
# 通過愛好,新增引用
hobby3.userobjects.add(user1)
hobby3.userobjects.add(user2)
print(user1.hobby2_set.all())
print(hobby3.userobjects.all())
# hobby3刪除引用的user1
hobby3.userobjects.remove(user1)
print(hobby3.userobjects.all())
'''【結果】 [<Hobby2: 中午寫程式碼>, <Hobby2: 早上寫程式碼>, <Hobby2: 晚上寫程式碼>] <QuerySet [<User2: name1>, <User2: name2>]> <QuerySet [<User2: name2>]>
'''
print(row.money, row.staff.name)
# 反差 點關聯表的表明小寫進行跨表查詢 row.salary.money
res = models.StaffInfo.objects.all()
for row in res:
print(row.name, row.salary.money)
7.6.3 through維護中間表
through指明中間表的模型類,如果自己指明瞭中間表,那麼django就不會幫助維護了,所有的新增刪除引用關係,都必須自己手動完成。
- model.py
class User3(models.Model):
name = models.CharField(max_length=16, unique=True)
# 使用者名稱
def __str__(self):
return str(self.name)
class Hobby3(models.Model):
name = models.CharField(max_length=16, unique=True)
# 愛好名稱
userobjects = models.ManyToManyField(to=User3,through='User3ToHobby3')
# 多對多
def \__str__(self):
return str(self.name)
class User3ToHobby3(models.Model):
user = models.ForeignKey(to=User3)
hobby = models.ForeignKey(to=Hobby3)
- 測試
# 建立使用者物件
user1 = User3.objects.create(name='name1')
user2 = User3.objects.create(name='name2')
# 建立愛好物件
hobby1 = Hobby3.objects.create(name='早上寫程式碼')
hobby2 = Hobby3.objects.create(name='中午寫程式碼')
hobby3 = Hobby3.objects.create(name='晚上寫程式碼')
# 自己手動維護中間表
User3ToHobby3.objects.create(user=user1,hobby=hobby1) User3ToHobby3.objects.create(user=user1,hobby=hobby2) User3ToHobby3.objects.create(user=user2,hobby=hobby2) User3ToHobby3.objects.create(user=user2,hobby=hobby3)
print(user1.hobby3_set.all())
print(hobby3.userobjects.all())
'''【結果】 >> <QuerySet [<Hobby3: 早上寫程式碼>, <Hobby3: 中午寫程式碼>]
>> <QuerySet [\<User3: name2\>]\>
'''
7.7 一對多 多對多 一對一的詳細例項
參考以下連結: https://blog.csdn.net/jiangbo721/article/details/89918381
8 中介軟體Middleware應用
8.1 概念
中介軟體是一個輕量級、底層的外掛系統,可以介入Django的請求和響應處理過程,修改Django的輸入或輸出
8.2 原理
在http請求 到達檢視函式之前 和檢視函式return之後,django會根據自己的規則在合適的時機執行中介軟體中相應的方法。Django1.9版本以後中介軟體的執行流程
- 執行完所有的request方法 到達檢視函式。
- 執行中介軟體的其他方法
- 經過所有response方法 返回客戶端。
注意:如果在其中1箇中介軟體裡 request方法裡return了值,就會執行當前中介軟體的response方法,返回給使用者 然後報錯。。不會再執行下一個中介軟體。
8.3 中介軟體的註冊
settings.py檔案內設定MIDDLEWARE的值。
8.4 方法詳解
8.4.1 init
沒有引數,伺服器響應第一個請求的時候自動呼叫,使用者確定是否啟用該中介軟體
8.4.2 process_request(self,request) 常用
- 在執行檢視前被呼叫,每個請求上都會呼叫
- 不返回或返回HttpResponse物件
- 沒有return或者return None 繼續呼叫其他檢視
- return response 則不會呼叫其他檢視
8.4.3 process_view(self,request,view_func,view_args,view_kwargs)
呼叫檢視之前執行,每個請求都會呼叫2.不返回或返回HttpResponse物件
8.4.4 process_template_response(self,request,response)
在檢視剛好執行完後進行呼叫,每個請求都會呼叫2.不返回或返回HttpResponse物件
8.4.5 process_response(self,request,response)
所有響應返回瀏覽器之前呼叫,每個請求都會呼叫2.不返回或返回HttpResponse物件3.必須return response
8.4.6 process_exception(self,request,exception)
- 當檢視丟擲異常時呼叫
- 不返回或返回HttpResponse物件
8.5 使用場景
由於中介軟體工作在
檢視函式執行前、執行後(像不像所有檢視函式的裝飾器!)適合所有的請求/一部分請求做批量處理
- 做IP限制
- 放在 中介軟體類的列表中,阻止某些IP訪問了;
- URL訪問過濾
- 如果使用者訪問的是login檢視(放過)如果訪問其他檢視(需要檢測是不是有session已經有了放行,沒有返回login),這樣就省得在多個檢視函式上寫裝飾器了!
- 快取(還記得CDN嗎?)
- 客戶端請求來了,中介軟體去快取看看有沒有資料,有直接返回給使用者,沒有再去邏輯層
執行檢視函
9 admin後臺管理
9.1 概念
- django amdin是django提供的一個後臺管理頁面,改管理頁面提供完善的html和css,使得你在通過Model建立完資料庫表之後,就可以對資料進行增刪改查
- 管理介面不是讓訪問網站的人使用的,它服務於網站管理者。 它用於網站的管理員。
9.2 建立管理員使用者
- 開啟treminal 輸入 python manage.py createsuperuser 然後回車
- 自定義使用者名稱,密碼,郵箱號
注: 輸入密碼是 密碼是不可見的,輸入時需要注意,.
9.3 admin登入
- 開啟主路由自帶的admin路由
- 啟動服務,在前臺輸入url127.0.0.1/埠號/admin
- 輸入剛才自定義的賬號密碼進行登入
9.4 admin管理後臺
9.4.1 admin.py
9.4.1.1 引數詳解
引數 | 說明 |
---|---|
@admin.register(模型類) | 在後臺註冊匯入的模型類 |
list_display | 定義展示的欄位 |
search_fields | 定義支援模糊查詢的欄位 |
filter_horizontal | 定義多表顯示 |
list_filter | 定義右側的過濾器 |
admin.site.site_header | 設定網站頁頭 |
admin.site.site_title | 設定頁面標題 |
admin.site.index_title | 設定首頁標語 |
9.4.1.2 程式碼例項
9.4.2 app.py
9.4.2.1 引數詳解
引數 | 說明 |
---|---|
verbose_name | 定義app顯示的名字 |
9.4.2.2 程式碼例項
9.4.3 model.py
9.4.3.1 引數詳解
引數 | 說明 |
---|---|
Blank 預設為Fasle | 新增欄位時不允許為空 |
Choices | 下拉選框和模型類欄位的繫結, Django中推薦CHOICES大寫 |
related_name | 自定義表的外來鍵,用於模型類的反向查詢 |
upload_to | 定義上傳檔案的儲存方法 |
9.4.3.2 程式碼例項
10 專案淺析
10.1 專案結構
10.1.1 static
存放專案中使用的 css,js,img,video檔案
10.1.2 templete
存放專案中使用的前端html檔案。
10.1.3 user
1.定義使用者的模型類。
2.指定後臺管理顯示的內容。
3.使用者的註冊,登入,退出 。
4.購物車的 顯示,增加,購買。
10.1.4 course
1.定義課程的模型類,圖片和視訊的儲存方式。
2.指定後臺管理顯示的內容。
3.前臺主頁課程的顯示。
4.課程詳情頁的載入。
5.視訊的播放
10.1.5 middleware
1.全域性context的定義
2.前臺登入後使用者的顯示。
3.使用者的登陸判斷,若沒登入則跳轉登入頁面
10.1.6 settings
10.1.6.1 INSTALLED_APPS
應用的載入
10.1.6.2 MIDDLEWAER
新增自定義的中介軟體檔案
10.1.6.3 TEMPLATES
10.1.6.4 DATABASES
注:資料庫和密碼換成自己本地使用的資料庫和密碼
10.1.6.5 語言和時區
10.1.6.6 static靜態檔案
10.2 專案執行
10.2.1 資料庫遷移
10.2.2 後臺管理員的建立
10.2.3 後臺資料的新增
1.啟動服務
2.訪問專案
注:訪問http://127.0.0.1:8000/admin 路由進行後臺使用者的登入.
注:新增使用者,課程種類,課程表.
10.3 功能解析
10.3.1主頁課程的展示
10.3.2 主頁登入,登出和使用者資訊顯示
10.3.3 課程詳情頁的展示.
10.3.4 購物車操作:加入,購買
注:user_shoppingcart.html中url快捷呼叫user_purcharse,攜帶課程id,完成購買。
10.3.4 課程觀看
相關文章
- Django Admin後臺管理:高效開發與實踐Django
- 收藏,Python 開發中有哪些高階技巧?Python
- Django框架急速開發內容管理系統後臺Django框架
- Java後端高階開發面試技巧解析Java後端面試
- Django高階之-快取Django快取
- [Django高階之forms元件]DjangoORM元件
- Reactjs前端、Python爬蟲、Nodejs後臺開發招聘React前端Python爬蟲NodeJS
- Python 高階特性Python
- Python開發微信公眾號後臺(系列二)Python
- Ubuntu下Python & Django開發環境搭建UbuntuPythonDjango開發環境
- Python Django開發的WebSSH 堡壘機PythonDjangoWeb
- 分分鐘教你Python Web開發框架DjangoPythonWeb框架Django
- Django自帶後臺使用配置Django
- Django自帶後臺管理配置Django
- Django配置後臺xadmin管理介面Django
- python第三章課後習題Python
- 招聘:PHP高階開發工程師PHP工程師
- Android高階開發突破瓶頸Android
- python高階函式Python函式
- Python高階--閉包Python
- Python後臺開發(第一章: 路由與模板)Python路由
- Python後臺開發(第二章: 模型類實現)Python模型
- 簡化 Django 開發的八個 Python 包DjangoPython
- python中web開發框架Django的學習PythonWeb框架Django
- 【廈門】招聘golang後端開發工程師(高併發高效能後臺服務框架)Golang後端工程師框架
- Java開發者的Python快速進修指南:物件導向--高階篇JavaPython物件
- 智慧家居方向招聘高階前端開發前端
- Hive 高階應用開發示例(一)Hive
- 高階QML 3D元件開發3D元件
- Django 自定義管理命令:從入門到高階Django
- Python模組高階技巧Python
- python- 函式高階Python函式
- Python字典的高階用法Python
- 【模組三】Python高階Python
- Python 函式進階-高階函式Python函式
- React開發管理後臺0React
- Node + Express 後臺開發 —— 起步Express
- leacmf通用api開發後臺ACMAPI