Python後臺開發(第二章: 模型類實現)

CSDN學院發表於2020-01-11

1 ORM原理與資料庫配置

1.1 模組安裝

程式碼部分:

pip install pymysql pip install mysqlclient

1.2 模組安裝常見問題

  • time out 超時解決方案: pip install 包名 --user-i https://pypi.tuna.tsinghua.edu.cn/simple
  • 缺少c ++ 外掛解決方案:https://www.jb51.net/article/151033.htm

1.3 Pycharm連線 Mysql

  • 保證pycharm是專業版.
  • 建立mysql連線.

在這裡插入圖片描述

在這裡插入圖片描述

  • 測試連線,當出現successful時,說明連線資訊無誤,可以正常使用pycharm操作mysql資料庫.

在這裡插入圖片描述

  • 連線資料庫可能遇到的問題:
pymysql.err.OperationalError: (1045, "Access denied for user'root'\@'localhost' (using password: YES/NO)")    
  • 解決方案: 檢查Pycharm使用的賬號密碼,與cmd下登入Mysql資料庫的賬號密碼是否一致.
unrecognized or represents more than one time zone. You must configureeither the server or JDBC driver (via the serverTimezone configurationproperty) to use a more specifc time zone value if you want to utilize timezone support.  時區錯誤
  • 解決方案:
    • cmd下 執行mysql_upgrade -uroot -p --force
    • 重啟mysql服務
    • 進入mysql
    • set global time_zone = ‘+8:00’;
    • flush privileges ;
    • show variables like ‘’%time_zone%’’ ;

1.4 Pycharm—資料庫建立

建立命令如下:

Create database [資料庫名] charset=’utf8’; 

注:

  • 使用pycharm建立資料庫的時候一定要注意: 宣告utf8字符集
  • 選中需要執行的sql語句,使用 ctrl+enter執行該語句.

1.5 ORM框架原理

在這裡插入圖片描述

  • django中內嵌了ORM框架,不需要直接面向資料庫程式設計,而是定義模型類,通過模型類和物件完成資料表的增刪改查操作。
  • ORM在專案與資料庫之間起橋樑作用,使用PyMySQL和mysqlclient連線Mysql資料庫的介面。
  • 在ORM框架中,它幫我們把類和資料表進行了一個對映,可以讓我們通過類和類物件就能操作它所對應的表格中的資料。例如:模型類BookInfo–對映到–> 資料表bookinfo。使資料庫設計更加簡單
  • ORM框架可以根據我們設計的類自動幫我們生成資料庫中的表格,省去了我們自己建表的過程,也就是我們下邊提到的資料庫遷移操作.
  • 用物件導向的方式去運算元據庫的建立表、增加、修改、刪除、查詢等操作。把物件導向中的類和資料庫表一一對應,通過操作類和物件,對資料表實現資料操作,不需要寫sql,由orm框架生成。
  • Django的orm操作本質上會根據對接的資料庫引擎,翻譯成對應的sql語句;所有使用Django開發的專案無需關心程式底層使用的是MySQL、Oracle、sqlite…,如果資料庫遷移,只需要更換Django的資料庫引擎即可

1.6 資料庫資訊配置

  1. 預設情況下,配置使用SQLite。若不使用SQLite作為資料庫,則需要額外的設定
  2. 其中ENGINE設定為資料庫後端使用。內建資料庫後端有:
'django.db.backends.postgresql'

'django.db.backends.mysql'

'django.db.backends.sqlite3'

'django.db.backends.oracle'

注:在實際的開發專案中,多數情況下使用的是Mysql資料庫引擎.

  1. Mysql資料庫引擎的配置:

在主路由的settings.py檔案中, 通過DATABASES項進行資料庫設定

DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 
                          'NAME': 'mydemo', 
                          'USER': 'root', 
                          'PASSWORD': '', 
                          'HOST': 'localhost', 
                          'PORT': '3306', } } 
  1. 資料庫連線欄位說明:
欄位 說明
NAME 使用得資料庫資料庫名稱
USER 資料庫登入用的賬戶
PASSWORD 資料庫登入用的密碼
HOST 資料庫伺服器的位置,我們一般資料庫伺服器和客戶端都是在一臺主機上面,所以一般預設都填127.0.0.1或者localhost
PORT 資料庫啟動的埠號
欄位 說明
NAME 使用得資料庫資料庫名稱
USER 資料庫登入用的賬戶
  1. start—資料庫資訊快捷鍵的配置
  • 開啟pycharm的設定檔案

在這裡插入圖片描述

  • 跳轉到快捷鍵配置介面

在這裡插入圖片描述

注: 搜尋框搜尋 live —> 點選Python的小箭頭 --點選+號 —選擇live template

  • 配置快捷鍵資訊

在這裡插入圖片描述
注: 配置完成,點選OK ,在settings中使用start進行測試使用.

2 Model模型層

2.1 Model 概述

  • 在Django中model是你資料的單一、明確的資訊來源。它包含了你儲存的資料的重要欄位和行為。通常,一個模型類(model)對映到一個資料庫表。
  • 定義簡介:
    • 每個模型都是一個python類,它是django.db.models.Model的子類
    • 模型的每個屬性都代表一個資料庫欄位
    • 綜上所述,Django為您提供了一個自動生成的資料庫訪問API,詳細見官方文件。
  • model與資料庫結構對應關係圖如下:

在這裡插入圖片描述

2.2 快速入門

下面舉類詳細分析model如何建立類,及各個語法的意義,如定義一個Person模型,包含兩個屬性first_name和last_name.

from  django.db import models class Person(models.Model): 
   #每個類都必須繼承models.Model 
	first_name = models.CharField(max_length=30)
	#資料庫中的列 
	last_name = models.CharField(max_length=30)
#資料庫中的列 
def Meta(self): 
    db_table = 'person'
    # 自定義建立的表名是person,不指定預設表名:myapp_person 

first_name 和last_name是模型的欄位,每個欄位被指定為一個類屬性,每個屬性對映到一個資料庫表的列。

上面的Person模型將會如下面sql語句在資料庫中建立一個表:

create  table  myapp_person( 
    'id':serial   not null primary key, 
    'first_name' varchar(30)  not null, 
    'last_name' varchar(30) not null, );

2.3 常用欄位

欄位 說明
AutoField 1.自增列 = int(11) 2.如果沒有的話,django 自動建立一個自增的id 列 3.如果要顯式的自定義一個自增列,必須設定primary_key=True。 4.一個model類不能有兩個自增的AutoField
CharField 1.字串欄位 2.必須設定max_length引數 3.如果超過254個字元,建議使用TextField。
BooleanField 1.布林型別=tinyint(1) 2.不能為空,可新增Blank=True
ComaSeparatedIntegerField 1.用逗號分割的數字=varchar 2.繼承CharField,所以必須 max_lenght 引數
ComaSeparatedIntegerField 1. 用逗號分割的數字=varchar 2. 繼承CharField,所以必須 max_lenght 引數
DateField 1.日期型別 date 2.DateField.auto_now:儲存時自動設定該欄位為現在日期,最後修改日期 3.DateField.auto_now_add:當該物件第一次被建立是自動設定該欄位為現在日期,建立日期。
DateTimeField 1.日期時間型別 datetime 2.同DateField的引數
Decimal 1.十進位制小數型別 = decimal 2.DecimalField.max_digits:數字中允許的最大位數 3.DecimalField.decimal_places:儲存的十進位制位數 例如,要儲存的數字最大長度為3位,而帶有兩個小數位,可以使用: models.DecimalField( max_digits=3, decimal_places=2,)
EmailField 一個帶有檢查 Email 合法性的 CharField
FloatField 浮點型別 = double
IntegerField 整形
BigIntegerField 長整形
GenericIPAddressField 一個帶有檢查 IP地址合法性的 CharField,儲存IP地址
NullBooleanField 允許為空的布林型別
PositiveIntegerFiel 正整數
PositiveSmallIntegerField 正smallInteger
SlugField 儲存 減號、下劃線、字母、數字
SmallIntegerField 1.數字 2.資料庫中的欄位有:tinyint、smallint、int、bigint
TextField 大文字。預設對應的form標籤是textarea
TimeField 時間 HH:MM[:ss[.uuuuuu]]
URLField 一個帶有URL合法性校驗的CharField
BinaryField 1.二進位制 2.儲存二進位制資料。不能使用filter函式獲得QuerySet。
ImageField 1.圖片 2.ImageField.height_field、ImageField.width_field:如果提供這兩個引數,則圖片將按提供的高度和寬度規格儲存。 3.該欄位要求 Python Imaging 庫Pillow。 4.會檢查上傳的物件是否是一個合法圖片。
FileField 1.FileField.upload_to:一個用於儲存上傳檔案的本地檔案系統路徑,該路徑由 MEDIA_ROOT 中設定 2.這個欄位不能設定primary_key和unique選項.在資料庫中儲存型別是varchar,預設最大長度為100
FilePathFiel 1.FilePathField.path:檔案的絕對路徑,必填 2.FilePathField.match:用於過濾路徑下檔名的正規表示式,該表示式將用在檔名上(不包括路徑)。 3.FilePathField.recursive:True 或 False,預設為 False,指定是否應包括所有子目錄的路徑。例如:FilePathField(path="/home/images", match=“foo.*”, recursive=True) 將匹配“/home/images/foo.gif”但不匹配“/home/images/foo/bar.gif”

2.4 常用欄位約束

欄位 說明
null 如果是True,Django會在資料庫中將此欄位的值置為NULL,預設值是False
blank 1.如果為True時django的 Admin 中新增資料時可允許空值,可以不填。如果為False則必須填。預設是False。 2.null純粹是與資料庫有關係的。而blank是與頁面必填項驗證有關的
primary_key= False 主鍵,對AutoField設定主鍵後,就會代替原來的自增 id 列
auto_now auto_now_add 1.auto_now 自動建立—無論新增或修改,都是當前操作的時間 2.auto_now_add 自動建立—永遠是建立時的時間
choices 1.一個二維的元組被用作choices,如果這樣定義,Django會select box代替普通的文字框, 2.並且限定choices的值是元組中的值
max_length 欄位長度
default 預設值
verbose_name Admin中欄位的顯示名稱,如果不設定該引數時,則與屬性名
db_column 資料庫中的欄位名稱
unique=True 不允許重複
db_index = True 資料庫索引
editable=True 在Admin裡是否可編輯
error_messages=None 錯誤提示
auto_created=False 自動建立
help_text 在Admin中提示幫助資訊
validators=[] 驗證器
upload-to 檔案上傳時的儲存上傳檔案的目錄

2.5 資料庫遷移

2.5.1 概念

對於django而言,強大之處就在於在通過遷移命令執行遷移後,會根據model.py檔案定義的類欄位生成對應的sql語句指令碼,進行相應的資料庫操作。

2.5.2 遷移命令

  • 對整個專案進行遷移
# 生成遷移檔案 
python manage.py makemigrations 
#執行遷移 
python manage.py migrate

  • 對單個app進行遷移
# 生成遷移檔案 
python manage.py makemigrations [模組名] 
#執行遷移 
python manage.py migrate [模組名]

注:

  • 執行遷移前,核對資料庫的連線資訊,賬號密碼的核對,資料庫是否存在.
  • 修改模型類後,若需要資料庫同步修改的內容,則需要重新進行遷移步驟,才可以完成欄位的同步
  • 寫好模型類後,在Pycharm的terminal 命令列進行資料的遷移和維護

2.6 模型類的增刪改查

2.6.1 定義模型類

class User(models.Model): 
    username = models.CharField(max_length= 16,unique= True ) 
    password = models.CharField(max_length= 16,default= "123456") 
    gender = models.PositiveSmallIntegerField(default= 0) 
    age = models.IntegerField(null= True ) 
    createDatetime = models.DateTimeField( auto_now_add= datetime.datetime.now()) 

注: terminal 命令列-- python manage.py makemigrations-- python manage.py migrate

2.6.2 進入shell互動式程式設計

  1. 在pycharm中的Terminal中輸入python manage.py shell,進入互動式程式設計
  2. 匯入user中的模型類: from user.models import *

2.6.3 增加資料

2.6.3.1 create方法

user = User.objects.create( username = "name2", ) 
#等價於
user = User(username="name2") 
user.save() 

2.6.3.2 模型物件.save() -推薦使用

user = User() 
user.username = 'name1' 
user.id 
user.save() 

注: 呼叫save方法後user物件封裝寫入資料庫中的資料內容

2.6.4 刪除資料

delete方法:

#第一種 根據id直接刪除 
user.delete() 
#先查詢後刪除,刪除的是查詢後的物件
User.objects.filter(id=2).delete() 

2.6.5 修改資料

2.6.5.1 save()

#修改user使用者的密碼為pass1 
user.password = 'pass1' user.save() 

注:若模型類中修改的id存在,則為修改資料,不存在,為新增資料

2.6.5.2 update()

User.objects.filter(【條件】).update(屬性=屬性值) 例如: User.objects.filter(id=2).update(password="pass2")

2.6.6 查詢資料

2.6.6.1 查詢語法格式

  1. 語法: 【模型類名】.objects.【方法】(【條件】)
  2. 常用方法
方法 說明
get() 返回滿足條件的單條資料
count() 返回查詢集中的資料個數
first() 取第一個值
last() 取最後一個值
exists() 判斷是否存在
all() 返回所有資料
filter(條件) 返回符合條件的資料
exclude(條件) 返回不符合條件的資料
values() 返回字典列表
order_by() 排序查詢. 預設為升序排列,降序可在欄位前加一個負號

注:

  • get屬於單條查詢方法,當查詢資料不存在時會引發異常(DoesNotExist),查詢到多個資料時也會引發異常(MultipleObjectsReturned)
  • all,filter,exclude.values,order_by屬於多條查詢方法
    • 從資料庫中獲取物件的集合(Queryset)。
    • 查詢集可以用過濾器篩選物件(filter(條件)),可以多次呼叫。
    • 過濾器實際就是一個函式
    • 過濾器產生新的查詢集
    • 查詢集就是一個Queryset的列表
    • 查詢集是不會訪問資料庫的,直到訪問資料時才訪問資料庫。如迭代、序列化、與if合用等

2.6.6.2 比較查詢

  1. 語法: 【欄位名】__【條件關鍵字】=【比較值】
  2. 條件引數:
條件 說明
相等 exact
大於 gt
大於等於 gte
小於 lt
小於等於 lte
為空查詢 isnull
  1. 例項:
#查詢id\>=2的所有使用者 
users = User.objects.filter(id__gte=2)

2.6.6.3 模糊查詢

  1. 條件引數
條件 說明
包含 contains
開頭 startswith
結尾 endswith
  1. 例項:
# 查詢使用者名稱中包含'1'的使用者 
user1_s = User.objects.filter(username__contains='1') 
# 查詢使用者名稱以'name1'開頭的使用者 
user2_s = User.objects.filter(username__startswith='name1') 
# 查詢郵箱以@qq.com'結尾的使用者 
user3_s = User.objects.filter(email__endswith='@qq.com') 

2.6.6.4 範圍查詢

  • 條件引數
條件 說明
範圍 in
  • 例項:
#查詢username屬於["name1","name2"]的user物件 
users = User.objects.filter(username__in= ["name1""name2"]

  1. 匯入方式: from django.db.models import F
  2. F物件的應用場景: 多數用於同行資料欄位間的互相比較
  3. 程式碼例項:
# 可以使用模型的欄位A與欄位B進行比較,如果A寫在了等號的左邊,則B出現在等號的右邊,需要通過F物件構造
list.filter(bread__gte=F('b_commet')) # django支援對F()物件使用算數運算
list.filter(bread__gte=F('b_commet') * 2)

  1. F()物件中還可以寫作“模型類__列名”進行關聯查詢list.filter(isDelete=F(‘heroinfo__isDelete’))
#對於date/time欄位,可與timedelta()進行運算
list.filter(bpub_date__lt=F('b_pub_date') + timedelta(days=1))

2.6.6.6 Q物件

  1. 匯入方式: from django.db.models import Q
  2. Q物件的應用場景: 多數用於欄位間的邏輯比較
  3. 程式碼例項:
#過濾器的方法中關鍵字引數查詢,會合併為And進行 
#需要進行or查詢,使用Q()物件 
#Q物件(django.db.models.Q)用於封裝一組關鍵字引數,這些關鍵字引數與“比較運算子”中的相同 
from django.db.models import Q list.filter(Q(pk__lt=6)) 
#Q物件可以使用&(and)、|(or)操作符組合起來 
#當操作符應用在兩個Q物件時,會產生一個新的Q物件 
list.filter(pk__lt=6).filter(b_commet__gt=10) 
list.filter(Q(pk__lt=6)|Q(b_commet__gt=10)) 
#使用~(not)操作符在Q物件前表示取反 
list.filter(~Q(pk__lt=6)) 
#可以使用&|~結合括號進行分組,構造做生意複雜的Q物件 
#過濾器函式可以傳遞一個或多個Q物件作為位置引數,如果有多個Q物件,這些引數的邏輯為and #過濾器函式可以混合使用Q物件和關鍵字引數,所有引數都將and在一起,Q物件必須位於關鍵字引數的前面 

2.7 懶載入

2.7.1 原理

  • 存在於外來鍵和多對多關係
  • 不檢索關聯物件的資料
  • 呼叫關聯物件會再次查詢資料庫
  • 執行res = models.Article.objects.all()這樣的類似查詢時,並沒有真正去資料庫操作取出、生成資料,而是生成Query_set迭代物件,當使用到模型類的資料時,才向資料庫載入資料的具體內容
  • 每次查詢回來資料,Django就會把這些資料儲存在cache中,當你下次使用時,不會去資料庫再次查詢,而是去cache裡面取,即減少了資料庫的壓力,又節省了記憶體.

2.7.2 例項

users = User.objects.all() 
for user in users: 
	print(user.username)

2.8 鏈式呼叫

2.8.1 原理

在使用QuerySet進行查詢操作的時候,可以提供多種操作。比如過濾完後還要根據某個欄位進行排序,那麼這一系列的操作我們可以通過一個非常流暢的鏈式呼叫的方式進行。

2.8.2 QuerySet方法引數

QuerySet方法 返回型別 說明
get() 模型物件 滿足條件的唯一物件
all() QuerySet 所有物件
filter() QuerySet 滿足條件的物件
exclude() QuerySet 不滿足條件的物件
order_by() QuerySet 排序
count() int 結果的數量
exists() boolean 結果是否存在

2.8.3 程式碼例項

#從文章表中獲取標題為123,並且提取後要將結果根據釋出的時間進行排序 
articles=Article.objects.filter(title='123').order_by('create_time') 

注: 可以看到order_by方法是直接在filter執行後呼叫的。這說明filter返回的物件是一個擁有order_by方法的物件。而這個物件正是一個新的QuerySet物件。因此可以使用order_by方法。

排序語法格式: order_by(【欄位1】,-【欄位2】)

#先根據欄位1升序排列,如果欄位1相同,則根據欄位2降序排列 例如:
user_s = User.objects.all().order_by('createDatetime','-birthday')

相關文章