前言
去github搜 "python orm",最高star居然不是sqlalchemy,而是peewee
后來得知peewee,比sqlalchemy簡單好用。值得一學哦!!
我總體感覺(peewee像 Django-ORM的分離版,,但比Django-ORM和SqlAlchemy 小巧,簡單,文檔也友好)
還有一個更重要的感覺就是, peewee 的 API方法名 和 SQL語句 的 單詞 基本相似。
例如對比一下(關鍵詞語法都是 update 和 where):
SQL語句:update Lang set name='Python' where name='Java';
Peewee:Lang.update(name='Python').where(Lang.name == 'Java')
這種良心的API,可以大大降低我們的學習成本,還可以鞏固我們對SQL的記憶!!!!!!
總官檔地址:http://docs.peewee-orm.com/en...
官方Github地址:https://github.com/coleifer/p...
安裝和導入
pip install peewee
from peewee import *
# peewee的模塊很結構化,都在peewee中,如果懶就都導入進來。 當然你也可以熟了,按需導入
# 后面無特殊情況,就都是這樣導入的。我就不提了。
數據庫
postgresql 和 sqlite
peewee 只支持 sqlite, mysql 和 postgresql 數據庫, 如果你有需求用oracle等,請繞行。。。
如需sqlite 和 postgresql,配置請參考 http://docs.peewee-orm.com/en...
mysql
當然我經常用MySQL,以后的所有都圍繞mysql來講,如下是基本配置
mysql_db = MySQLDatabase(
'lin', # 數據庫
user='root', # 用戶名
password='123', # 密碼
host='IP', # IP
port=3306, # 端口
charset='utf8mb4' # 字符集類型, utf8mb4 是 utf8的大哥
)
peewee的mysql引擎默認優先使用pymysql。
如果你沒安裝pymysql, 他就會去尋找 MySQLdb。 都沒有就會報錯。
嗯,都啥年代了,python3的時代,所以我們用 pymysql模塊即可,若沒安裝,跳出來安裝下即可
pip install pymysql
既然用的pymysql驅動,MySQLDatabase() 里面的寫法 和 pymysql對象實例化的參數配置是一樣的。
如果我給的例子的參數不夠用,你可以來下面的鏈接自己選吧:https://github.com/PyMySQL/Py...
建立數據庫連接
print(mysql_db.connect())
關閉數據庫連接
print(mysql_db.close())
測試數據庫連接是否關閉
mysql_db.is_closed()
列出數據庫的所有表:
mysql_db.get_tables()
列出所有字段的詳細信息:
print(db.get_columns('owner')) # 假設 owner是表名,下面同理
列出所有主鍵的字段:
print(db.get_primary_keys('owner'))
列出所有索引字段的詳細信息:
print(db.get_indexes('owner'))
列出所有外鍵的字段:
print(db.get_foreign_keys('owner'))
Python 各種 web框架嵌入使用 peewee 案例傳送門:
官檔-Web案例:http://docs.peewee-orm.com/en...
表-記錄-字段
ORM語法 和 數據庫的 (表-記錄-字段)對應關系如下:
ORM結構 | 數據庫 |
類 | 表 |
實例(對象) | 記錄 |
類屬性 | 列 |
默認自增主鍵ID
定義一個類,繼承了peewee模塊的Model類,這個類就可以當作Model來用了
首先建立一張"空表"
mysql_db = MySQLDatabase('lin_test', user='root', password='123',
host='ip', port=3306, charset='utf8mb4')
class Owner(Model):
class Meta:
database=mysql_db # 這里是"必須" 要指定的, 指定哪一數據庫
mysql_db.create_tables([Owner]) # 注意,源碼是取出參數遍歷,所以這里參數用列表
上述代碼就可以建立一張"空表"。 為什么"空表" 用引號括起來呢??
這是關于peewee orm的機制,"你若不指定(primary key)",它就會"自動"為你創建一個
"名為 id", "類型為 int", 并設置為 "primary" 的 "自增(auto_increment)" 的字段
但 一旦你把一個自定義的字段,設為主鍵,默認的id字段就會被覆蓋:
name = CharField(primary_key=True) # name設為了主鍵, 原有的默認id就沒了
官檔也說明:如果你想自己建立一個自增主鍵,并覆蓋默認id。你可以用AutoField字段:
new_id = AutoField() # 這句話直接就為你 設置為 int型 和 主鍵 和自增。
"這是官檔最推薦覆蓋id的方法, 而不是自己弄一個 Integer,再設主鍵"
自增id就講完了, 不過你是否發現每個 類下都有
class Meta:
database= xxx # 這是為每張表指定數據庫,必須要指定的。不然它不知道你這個表在哪個數據庫
既然這樣,若我們要在一個數據庫中創建很多很多表,那豈不是每次都需要給每張表指定一個數據庫??
就像這樣:
class User(Model):
class Meta:
database = mysql_db
class Owner(Model):
class Meta:
database = mysql_db
這樣有點煩,但我們可以定義一個基類指定好數據庫, 然后其他子類模型繼承它就好了。
class BaseModel(Model):
name = CharField(max_length=10) # 定義一個 name 字段
class Meta:
database = mysql_db
class User(BaseModel): # 繼承基類
pass
class Owner(BaseModel): # 繼承基類
pass
mysql_db.create_tables([User, Owner]) # 正式創建表, 基類不需要,可以不放進來
像上述代碼CharField, 更多類型字段定義,官檔給的很詳細了,我不再贅述了。
官檔-字段-參數:http://docs.peewee-orm.com/en...
但下面我還會挑一些主要常用(有一點點點難特別)的說一下。。。
外鍵字段(ForeignKeyField)
普通外鍵
class BaseModel(Model): # 基類
name = CharField(max_length=10)
class Meta:
database = mysql_db
class Owner(BaseModel): # 主人類
pass
class Pet(BaseModel): # 寵物類
owner = ForeignKeyField(
Owner,
backref='owner_conn', # 通過引用名獲取對象。"主人,你可以通過這個名字調用我"
on_delete='Cascade', # 級聯刪除
# 默認為None, 這時,你想刪主人是刪不掉的。會報錯。 必須先刪寵物再刪主人。
# 設為 Cascade后, 你可以直接刪主人。 他的寵物也會隨之自動刪除。 這就是級聯刪除
on_update=Cascade, # 級聯更新,原理同 on_delete
)
層級外鍵(通常用于層級分類,自關聯查詢):
class Category(BaseModel):
name = CharField()
parent = ForeignKeyField('self', null=True, backref='children')
注: "self" 字符串是固定語法, 下一篇還會將,自關聯查詢
日期字段(DateTimeField)
import datetime
......
date_time= DateTimeField(default=datetime.datetime.now)
表屬性(Meta)
表屬性就是可以 改表名,設置主鍵,聯合主鍵,設置索引,聯合索引等操作。不再贅述,見官檔。
官檔 Meta: http://docs.peewee-orm.com/en...
索引 和 約束
設置索引有3種方法:
-
通過定義字段的參數:
普通索引name = CharField(index=True)
唯一索引
name = CharField(unique=True)
-
通過定義表屬性Meta:
聯合唯一索引class Meta: indexes = ( (('字段1', '字段2'), True), # 字段1與字段2整體作為索引,True 代表唯一索引 (('字段1', '字段2'), False), # 字段1與字段2整體作為索引,False 代表普通索引 ) 需要注意的是,上面語法,三層元組嵌套, 元組你懂得, 一個元素時需要加個 , 逗號。 別忘了。
-
索引API:
官檔:http://docs.peewee-orm.com/en...
設置約束有2種方法:
-
通過定義字段的參數:
-------通常用來單一字段主鍵:name = CharField(primary_key=True)
-
通過定義表屬性Meta
-------通常用作聯合主鍵:class Meta: primary_key = CompositeKey('字段1', '字段2') # primary_key = False # 也可以不使用主鍵(不覆蓋,也 取消 創建默認id字段)
事務
支持with上下文語法,支持事務嵌套,注意嵌套事務 只會回滾 離它最近 的一層之間的代碼。
包裹在with語句中的代碼,只要存在異常,就會回滾。嵌套的事務,也是有一處異常,所有層事務都會回滾。
當然你也可以手動 rollback()來回滾。
嵌套事務示例如下:
with mysql_db.atomic() as transaction1: # 第一層事務。 atomic(), 固定語法就不說了。
User.create(username='Tom')
with mysql_db.atomic() as transaction2: # 第二層事務
User.create(username='Jerry')
User.create(username='Spike')
transaction2.rollback() # 就近原則, 第二層的rollback()回滾
User.create(username='Butch')
# 如果真的出現回滾,那么 從 第二層的 with() 開始算 事務內容, 到 rollback() 結束
# 形象例子: 頂部 面包片從 第二層的with()開始夾, 底部 面包片 夾到 rollback()
# 注意一點,雖然是嵌套事務,但是每層with事務都有對應的名字(就是with as 之后變量)。
# 所以回滾寫在哪層事務里面, 就要用哪層事務的名字(就近原則)。 不然會報錯的。
# 錯誤實例: 倒數第二行的: transaction2.rollback() 寫成 transaction1.rollback()。 錯誤!
帶有commit()的嵌套事務示例如下:(縮小事務的代碼范圍, 就像 "面包里夾的東西變少了" 的意思)
with mysql_db.atomic() as transaction1: # 第一層事務
User.create(username='Tom')
with mysql_db.atomic() as transaction2: # 第二層事務
User.create(username='Jerry')
transaction2.commit() # 就這里變了, 插入了一行 commit
User.create(username='Spike')
transaction2.rollback() # rollback()回滾
User.create(username='Butch')
# commit(),加入了這一行,就意味著 從 這行開始算 回滾內容,到 rollback() 結束
# 形象例子: (頂部 面包片 從commit() 這里開始夾, 底部 面包片 夾到 rollback() )
上面無論哪個事務例子, 都必須注意:
- 每層事務,只管自己層內的 rollback(),才有效, 不能管其他層的。
- 就算你用 commit() 夾, 如果自己層內沒有 rollback(), 那么你的 commit()是無效的(夾不住)
事務就差不多這些,官檔還有一些用法和語法,但最終功能結果都是一樣的。選一種(我的例子)就行。
官檔-事務: http://docs.peewee-orm.com/en...
閑雜用法
查看ORM對應的原生SQL語句:
.....ORM語句.sql() # 后綴 .sql() 打印對應原生sql
執行原生SQL:
# 注意,傳數據用參數,不要用字符串拼接(防SQL注入)
for owner in Owner.raw('select * from owner where name=%s', 'Alice'):
print(owner.name)
更原生的執行原生SQL:
print(mysql_db.execute_sql('select * from user').fetchall())
# sql,可以傳位置參數(防注入),就像使用 pymysql一樣。
表改名:
注:我說的改名只是查詢時的臨時名
下一篇文章查詢,會提到 字段改名, 格式: 字段.alias('新字段名')
那表改名也差不多,有2種方式:
方式1:
格式: 表類.alias('新表名')
方式2:
格式: 新表名 = 表類.alias()
未結束語
本篇寫了一些入門性的模型的建立,數據庫,事務,索引,算是比較基本的。
當然還有更常用,更重要的CRUD等,會在下一篇介紹。
下一篇傳送門:https://segmentfault.com/a/11...
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
