Python之路【第十七篇】:Django【進階篇 】
Model
到目前為止,當我們的程序涉及到數據庫相關操作時,我們一般都會這麽搞:
- 創建數據庫,設計表結構和字段
- 使用 MySQLdb 來連接數據庫,並編寫數據訪問層代碼
- 業務邏輯層去調用數據訪問層執行數據庫操作
django為使用一種新的方式,即:關系對象映射(Object Relational Mapping,簡稱ORM)。
PHP:activerecord
Java:Hibernate
C#:Entity Framework
django中遵循 Code Frist 的原則,即:根據代碼中定義的類來自動生成數據庫表。
一、創建表
1、基本結構
1 2 3 4 5 6 |
from django.db import models
class userinfo(models.Model):
name = models.CharField(max_length = 30 )
email = models.EmailField()
memo = models.TextField()
|
2、連表結構
- 一對多:models.ForeignKey(其他表)
- 多對多:models.ManyToManyField(其他表)
- 一對一:models.OneToOneField(其他表)
字段以及參數應用場景:
- 一對多:當一張表中創建一行數據時,有一個單選的下拉框(可以被重復選擇)
例如:創建用戶信息時候,需要選擇一個用戶類型【普通用戶】【金牌用戶】【鉑金用戶】等。- 多對多:在某表中創建一行數據是,有一個可以多選的下拉框
例如:創建用戶信息,需要為用戶指定多個愛好- 一對一:在某表中創建一行數據時,有一個單選的下拉框(下拉框中的內容被用過一次就消失了
例如:原有含10列數據的一張表保存相關信息,經過一段時間之後,10列無法滿足需求,需要為原來的表再添加5列數據
二、操作表
1、基本操作
基本操作2、進階操作(了不起的雙下劃線)
利用雙下劃線將字段和對應的操作連接起來
3、其他操作
其他操作4、連表操作(了不起的雙下劃線)
利用雙下劃線和 _set 將表之間的操作連接起來
表結構實例 一對一操作 一對多 多對多操作擴展:
a、自定義上傳
View Codeb、Form上傳文件實例
Form Model ViewForm
django中的Form一般有兩種功能:
- 輸入html
- 驗證用戶輸入
擴展:ModelForm
在使用Model和Form時,都需要對字段進行定義並指定類型,通過ModelForm則可以省去From中字段的定義
View Code跨站請求偽造
一、簡介
django為用戶實現防止跨站請求偽造的功能,通過中間件 django.middleware.csrf.CsrfViewMiddleware 來完成。而對於django中設置防跨站請求偽造功能有分為全局和局部。
全局:
中間件 django.middleware.csrf.CsrfViewMiddleware
局部:
- @csrf_protect,為當前函數強制設置防跨站請求偽造功能,即便settings中沒有設置全局中間件。
- @csrf_exempt,取消當前函數防跨站請求偽造功能,即便settings中設置了全局中間件。
註:from django.views.decorators.csrf import csrf_exempt,csrf_protect
二、應用
1、普通表單
+ View Code2、Ajax
對於傳統的form,可以通過表單的方式將token再次發送到服務端,而對於ajax的話,使用如下方式。
view.py
+ View Codetext.html
+ View Code更多:https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
Cookie
1、獲取Cookie:
1 2 3 4 5 6 |
request.COOKIES[ ‘key‘ ]
request.get_signed_cookie(key, default = RAISE_ERROR, salt = ‘‘, max_age = None )
參數:
default: 默認值
salt: 加密鹽
max_age: 後臺控制過期時間
|
2、設置Cookie:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
rep = HttpResponse(...) 或 rep = render(request, ...)
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt = ‘加密鹽‘ ,...)
參數:
key, 鍵
value = ‘‘, 值
max_age = None , 超時時間
expires = None , 超時時間(IE requires expires, so set it if hasn‘t been already.)
path = ‘/‘ , Cookie生效的路徑, / 表示根路徑,特殊的:跟路徑的cookie可以被任何url的頁面訪問
domain = None , Cookie生效的域名
secure = False , https傳輸
httponly = False 只能http協議傳輸,無法被JavaScript獲取(不是絕對,底層抓包可以獲取到也可以被覆蓋)
|
由於cookie保存在客戶端的電腦上,所以,JavaScript和jquery也可以操作cookie。
1 2 |
<script src = ‘/static/js/jquery.cookie.js‘ >< / script>
$.cookie( "list_pager_num" , 30 ,{ path: ‘/‘ });
|
Session
Django中默認支持Session,其內部提供了5種類型的Session供開發者使用:
- 數據庫(默認)
- 緩存
- 文件
- 緩存+數據庫
- 加密cookie
1、數據庫Session
+ View Code2、緩存Session
+ View Code3、文件Session
+ View Code4、緩存+數據庫Session
+ View Code5、加密cookie Session
+ View Code更多參考:猛擊這裏 和 猛擊這裏
擴展:Session用戶驗證
1 2 3 4 5 6 7 |
def login(func):
def wrap(request, * args, * * kwargs):
# 如果未登陸,跳轉到指定頁面
if request.path = = ‘/test/‘ :
return redirect( ‘http://www.baidu.com‘ )
return func(request, * args, * * kwargs)
return wrap
|
分頁
一、Django內置分頁
views.py Html 擴展內置分頁:views.py 擴展內置分頁:Html二、自定義分頁
分頁功能在每個網站都是必要的,對於分頁來說,其實就是根據用戶的輸入計算出應該在數據庫表中的起始位置。
1、設定每頁顯示數據條數
2、用戶輸入頁碼(第一頁、第二頁...)
3、根據設定的每頁顯示條數和當前頁碼,計算出需要取數據表的起始位置
4、在數據表中根據起始位置取值,頁面上輸出數據
需求又來了,需要在頁面上顯示分頁的頁面。如:[上一頁][1][2][3][4][5][下一頁]
1、設定每頁顯示數據條數
2、用戶輸入頁碼(第一頁、第二頁...)
3、設定顯示多少頁號
4、獲取當前數據總條數
5、根據設定顯示多少頁號和數據總條數計算出,總頁數
6、根據設定的每頁顯示條數和當前頁碼,計算出需要取數據表的起始位置
7、在數據表中根據起始位置取值,頁面上輸出數據
8、輸出分頁html,如:[上一頁][1][2][3][4][5][下一頁]
分頁實例總結,分頁時需要做三件事:
- 創建處理分頁數據的類
- 根據分頁數據獲取數據
- 輸出分頁HTML,即:[上一頁][1][2][3][4][5][下一頁]
緩存
由於Django是動態網站,所有每次請求均會去數據進行相應的操作,當程序訪問量大時,耗時必然會更加明顯,最簡單解決方式是使用:緩存,緩存將一個某個views的返回值保存至內存或者memcache中,5分鐘內再有人來訪問時,則不再去執行view中的操作,而是直接從內存或者Redis中之前緩存的內容拿到,並返回。
Django中提供了6種緩存方式:
- 開發調試
- 內存
- 文件
- 數據庫
- Memcache緩存(python-memcached模塊)
- Memcache緩存(pylibmc模塊)
1、配置
a、開發調試
View Codeb、內存
View Codec、文件
View Coded、數據庫
View Codee、Memcache緩存(python-memcached模塊)
View Codef、Memcache緩存(pylibmc模塊)
View Code2、應用
a. 全站使用
View Codeb. 單獨視圖緩存
View Codec、局部視圖使用
View Code更多:猛擊這裏
序列化
關於Django中的序列化主要應用在將數據庫中檢索的數據返回給客戶端用戶,特別的Ajax請求一般返回的為Json格式。
1、serializers
1 2 3 4 5 |
from django.core import serializers
ret = models.BookType.objects. all ()
data = serializers.serialize( "json" , ret)
|
2、json.dumps
1 2 3 4 5 6 7 8 |
import json
#ret = models.BookType.objects.all().values(‘caption‘)
ret = models.BookType.objects. all ().values_list( ‘caption‘ )
ret = list (ret)
result = json.dumps(ret)
|
由於json.dumps時無法處理datetime日期,所以可以通過自定義處理器來做擴展,如:
+ View Code信號
Django中提供了“信號調度”,用於在框架執行操作時解耦。通俗來講,就是一些動作發生的時候,信號允許特定的發送者去提醒一些接受者。
1、Django內置信號
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
Model signals
pre_init # django的modal執行其構造方法前,自動觸發
post_init # django的modal執行其構造方法後,自動觸發
pre_save # django的modal對象保存前,自動觸發
post_save # django的modal對象保存後,自動觸發
pre_delete # django的modal對象刪除前,自動觸發
post_delete # django的modal對象刪除後,自動觸發
m2m_changed # django的modal中使用m2m字段操作第三張表(add,remove,clear)前後,自動觸發
class_prepared # 程序啟動時,檢測已註冊的app中modal類,對於每一個類,自動觸發
Management signals
pre_migrate # 執行migrate命令前,自動觸發
post_migrate # 執行migrate命令後,自動觸發
Request / response signals
request_started # 請求到來前,自動觸發
request_finished # 請求結束後,自動觸發
got_request_exception # 請求異常後,自動觸發
Test signals
setting_changed # 使用test測試修改配置文件時,自動觸發
template_rendered # 使用test測試渲染模板時,自動觸發
Database Wrappers
connection_created # 創建數據庫連接時,自動觸發
|
對於Django內置的信號,僅需註冊指定信號,當程序執行相應操作時,自動觸發註冊函數:
View Code View Code2、自定義信號
a. 定義信號
1 2 |
import django.dispatch
pizza_done = django.dispatch.Signal(providing_args = [ "toppings" , "size" ])
|
b. 註冊信號
1 2 3 4 5 |
def callback(sender, * * kwargs):
print ( "callback" )
print (sender,kwargs)
pizza_done.connect(callback)
|
c. 觸發信號
1 2 3 |
from 路徑 import pizza_done
pizza_done.send(sender = ‘seven‘ ,toppings = 123 , size = 456 )
|
由於內置信號的觸發者已經集成到Django中,所以其會自動調用,而對於自定義信號則需要開發者在任意位置觸發。
更多:猛擊這裏
Python之路【第十七篇】:Django【進階篇 】