Python的魔法ORM --《PonyORM教程》 1.連接,聲明和查詢

前言

在非django框架的ORM當(dāng)中,我們有很多選擇规伐,包括大名鼎鼎的重量級(jí)選手sqlalchemy和頗受歡迎的輕量級(jí)明星peewee蟹倾,這2者的的介紹和教程網(wǎng)上到處都是,我這里就不介紹了猖闪。因?yàn)橐粋€(gè)偶然的機(jī)會(huì)鲜棠,了解到還有一款輕量級(jí)的orm---ponyorm, 官網(wǎng)在此https://ponyorm.org培慌。被它的低學(xué)習(xí)成本和高度抽象化所吸引豁陆,本著獨(dú)樂(lè)樂(lè)不如眾樂(lè)樂(lè)的原則,特別介紹給大家吵护,??目的是為了大家在使用python的ORM時(shí)有更多的選擇盒音。

首先,這是一款戰(zhàn)斗民族(俄羅斯)的作品馅而,印象中祥诽,俄羅斯的東西都是自帶黑魔法屬性的,比如 Kaspersky瓮恭,nginx之流??????

相對(duì)其他的ORM有以下幾個(gè)特點(diǎn):

  • 學(xué)習(xí)成本低: 沒(méi)有復(fù)雜的聲明方式和眼花繚亂的查詢語(yǔ)法雄坪,使用python原生類型定義字段。入門很容易偎血。
  • 抽象程度高: 對(duì)數(shù)據(jù)庫(kù)方面的預(yù)備知識(shí)要求很少,使用起來(lái)有種黑魔法的感覺(jué)盯漂,所以也常被成為只有Python魔法少女才知道的ORM
  • 使用便捷 相比其他的ORM颇玷,pony使用更少的代碼實(shí)現(xiàn)了同樣操作。代碼簡(jiǎn)潔就缆,大量的缺省值的設(shè)定非常合理帖渠,即使是新手,也能寫(xiě)出可靠竭宰,簡(jiǎn)潔的程序空郊。
  • 在線的模型編輯器很上手:在編輯上設(shè)計(jì)好模型,直接可以生成代碼和sql語(yǔ)句,對(duì)于小型團(tuán)隊(duì)開(kāi)發(fā)切揭,這個(gè)非常提升效率狞甚。

好了,下面開(kāi)始

以下示范以u(píng)buntu 18.04 + python3.6為例廓旬,你的系統(tǒng)可能有所不同哼审。請(qǐng)自行調(diào)整。

安裝

pip install pony

建立數(shù)據(jù)庫(kù)連接

新建一個(gè) pony_db.py 文件,輸入如下代碼

# -*- coding: utf-8 -*-
from pony.orm import *  # 引入
from datetime import date
from datetime import datetime


setting = {
    "provider": "mysql",    # 聲明數(shù)據(jù)庫(kù)種類
    "host": "127.0.0.1",    # 數(shù)據(jù)庫(kù)主機(jī)地址,也可以是域名
    "port": 3306,           # 端口
    "database": "test_db",  # 數(shù)據(jù)庫(kù)名
    "user": "test_01",      # 用戶名
    "password": "123456",   # 密碼
    "charset": "utf8mb4",   # 字符集
}
db = Database(**setting)  # 生成數(shù)據(jù)庫(kù)引擎


class Employee(db.Entity):
    """員工類"""
    _table_ = "employee"
    name = Required(str, max_len=40, unique=False, nullable=False, default="無(wú)名氏")  # 姓名
    age = Optional(int, size=8, nullable=True, default=None)  # 年齡
    born = Required(date, nullable=False, column="born_date", default=date.today)  # ??出生年月日


if __name__ == "__main__":
    db.drop_table(table_name="employee", if_exists=True, with_all_data=True)  # 刪除表涩盾,演示實(shí)體聲明時(shí)用于快速清除舊表
    db.generate_mapping(create_tables=True)  # 生成實(shí)體十气,表和映射關(guān)系
    pass

setting 是數(shù)據(jù)庫(kù)的配置聲明,這點(diǎn)每什么好記說(shuō)明的春霍,天下sql幾乎都是這么配置的....
class Employee(db.Entity) 這是我們定義的實(shí)體類砸西,這里有一個(gè)要求,db.Entity是實(shí)體模板類址儒,你的實(shí)體類必須繼承db.Entity類芹枷。

實(shí)體聲明

下面是字段聲明:

  • table : 定義表名
  • 字段名: 等號(hào)的左邊是字段名,也是數(shù)據(jù)庫(kù)的表中對(duì)應(yīng)的列的名字离福,這沒(méi)啥好說(shuō)的杖狼,當(dāng)然,如果希望重新定義表中對(duì)應(yīng)的列的名字妖爷,可以在后面的字段定義中使用 column="new_name"的方法來(lái)定義.
  • 字段種類: Required和Optional是定義字段的種類的聲明蝶涩,pony共有 Required,Optional絮识,PrimaryKey 绿聘,Set,和Discriminator5種字段的聲明:
  • Required 定義一個(gè)創(chuàng)建實(shí)例時(shí)次舌,必須提供的字段熄攘,注意,這里定義的不是數(shù)據(jù)庫(kù)的字段的not null選項(xiàng)
  • Optional 定義一個(gè)創(chuàng)建實(shí)例時(shí)彼念,可選的字段挪圾,注意,這里定義的不是數(shù)據(jù)庫(kù)的字段的not null選項(xiàng)
  • PrimaryKey 定義一個(gè)主鍵的逐沙,由于pony默認(rèn)會(huì)聲明一個(gè)int類型的自增主鍵哲思,所以這個(gè)聲明很少用到
  • Set 定義一個(gè)幾何類型的字段,一般用作一對(duì)多的多方和多對(duì)多情況的聲明吩案。
  • Discriminator 定義一個(gè)鑒別字段棚赔,用于區(qū)別父類和子類的表,這個(gè)字段在實(shí)體的繼承中我們會(huì)講到徘郭,現(xiàn)在請(qǐng)無(wú)視靠益。
  • 字段類型 字段聲明的第一個(gè)參數(shù)時(shí)字段類型,你可以看到残揉,pony沒(méi)有額外定義字段(當(dāng)然也不需要你引入各種String胧后,Integer之類的),直接使用python的原生的字段類型進(jìn)行聲明抱环,這些字段類型包括: int, str, date, datetime等(需要數(shù)據(jù)庫(kù)支持)绩卤,
  • 聲明參數(shù) 字段聲明的除第一個(gè)參數(shù)外途样,都是對(duì)聲明的參數(shù)進(jìn)行定義的參數(shù),常用的定義如下:
  • max_len: 字段長(zhǎng)度濒憋, str 類型特有.
  • size: 數(shù)字的大小范圍何暇,int類型特有. 8,16,32,64 默認(rèn)32,對(duì)應(yīng)mysql定義的 INT(11)
  • nullable: 字段的not null選項(xiàng)凛驮, Optional聲明的字段裆站,這里必須是True,
  • default: 字段的默認(rèn)值黔夭, nullable=True的字段必須是提供默認(rèn)值宏胯,可以時(shí)函數(shù)的返回值
  • unique: 是否唯一

生成映射

db.generate_mapping(create_tables=True)  # 生成實(shí)體,表和映射關(guān)系

上面這行代碼的意思就是創(chuàng)建表本姥,實(shí)體類的映射關(guān)系 肩袍,這種映射關(guān)系非常重要,pony在啟動(dòng)項(xiàng)目時(shí)會(huì)檢查整個(gè)項(xiàng)目的所有實(shí)體類的映射關(guān)系是否正確婚惫。所以氛赐,隨著項(xiàng)目的實(shí)體類越來(lái)越多,這個(gè)檢查的過(guò)程會(huì)越來(lái)越漫長(zhǎng)先舷。這也是pony為數(shù)不多的缺陷之一吧艰管。

增刪改查

    with db_session:
        emp = Employee(name="張三", age=12)  # 創(chuàng)建一個(gè)實(shí)例
        emp_dict = emp.to_dict()  # 實(shí)例轉(zhuǎn)字典
        print(emp_dict)
        emp.set(age=14)  # 修改字段
        emp = Employee.get(name="張三")  # 查找名字叫張三的員工
        print(emp.to_dict())
        emp.delete()  # 刪除實(shí)例
        emp = Employee.get(name="張三")  # 查找名字叫張三的員工
        print(emp)
  • db_session: 這是數(shù)據(jù)庫(kù)會(huì)話的上下文管理器,操作者必須使用 with 關(guān)鍵字保證對(duì)數(shù)據(jù)庫(kù)的操作都位于db_session的上下文空間之內(nèi)(偷偷告訴你蒋川,更推薦你用@db_session這個(gè)裝飾器哦)
  • to_dict: 實(shí)體類的實(shí)例使用此方法輸出dict格式的對(duì)象牲芋。
  • get: 根據(jù)條件,查詢一個(gè)實(shí)例捺球,如果給定的查詢條件返回的查詢結(jié)果不止一個(gè)缸浦,會(huì)拋出 pony.orm.core.MultipleObjectsFoundError: Multiple objects were found. Use Employee.select(...) to retrieve them 的錯(cuò)誤提醒,如果你需要查詢多個(gè),請(qǐng)使用 select 方法氮兵。
  • set: 修改實(shí)例的屬性裂逐,你可以使用 emp.set(**kwargs)的方法一次修改實(shí)例的多個(gè)屬性
  • delete: 沒(méi)什么好說(shuō)的,就是刪除實(shí)例

例子

查詢多個(gè)實(shí)例對(duì)象
修改Employee類的代碼胆剧,增加一個(gè)find_many的方法

    @classmethod
    @db_session
    def find_many(cls, **kwargs) -> list:
        """
        根據(jù)查詢條件查詢多個(gè)實(shí)例對(duì)象
        :param kwargs: 查詢條件
        :return:
        """
        handler = select(x for x in cls)
        """注意handler的鏈?zhǔn)秸{(diào)用"""
        for name, val in kwargs.items():
            handler = handler.where(lambda x: getattr(x, name=name) == val)
        result = [x.to_dict() for x in handler]
        return result

表里有如下數(shù)據(jù):


2019-10-09 17-07-47 的屏幕截圖.png

查詢

print(Employee.find_many(age=15))
print(Employee.find_many(age=15, name='john'))
[{'id': 2, 'name': 'jack', 'age': 15, 'born': datetime.date(2019, 10, 9)}, {'id': 4, 'name': 'john', 'age': 15, 'born': datetime.date(2019, 10, 10)}]
[{'id': 4, 'name': 'john', 'age': 15, 'born': datetime.date(2019, 10, 10)}]
Process finished with exit code 0

說(shuō)明:

  • @classmethod 類方法的裝飾器絮姆。表明此方法可以直接被類對(duì)象調(diào)用
  • @db_session 是數(shù)據(jù)庫(kù)會(huì)話的裝飾器醉冤,被此裝飾器裝飾的方法秩霍,內(nèi)部的代碼都運(yùn)行在是數(shù)據(jù)庫(kù)會(huì)話的上下文之間,這也是pony官方推薦的做法蚁阳,和使用 with db_session 上下文管理器相比铃绒,前者支持事務(wù)的嵌套操作。
  • select 查詢方法(最常用的查詢方法之一)螺捐,一般用于指定條件查詢多個(gè)對(duì)象颠悬,條件一般用 x for x in cls 這樣的表達(dá)式來(lái)指定矮燎。有別于需要額外學(xué)習(xí)的查詢語(yǔ)法,這樣的表達(dá)式本身就是python的表達(dá)式赔癌,無(wú)需額外的學(xué)習(xí)成本诞外,理解起來(lái)也很方表,使用表達(dá)式查詢是pony的的亮點(diǎn)之一灾票,也是pony高級(jí)抽象化的特征.此函數(shù)返回一個(gè)Query對(duì)象峡谊,這個(gè)對(duì)象本身的絕大多數(shù)方法的執(zhí)行結(jié)果就是返回self。這樣很方便的讓用戶以鏈?zhǔn)秸{(diào)用的方式刊苍,拼接一個(gè)復(fù)雜的查詢既们。而Query對(duì)象本身就是一個(gè)可迭代的對(duì)象,可以很方便的用[x for x in handler]類似的方法取出結(jié)果集正什。

索引

  1. Python的魔法ORM --《PonyORM教程》 1.連接,聲明和查詢
  2. Python的魔法ORM --《PonyORM教程》 2 實(shí)體關(guān)系
  3. Python的魔法ORM --《PonyORM教程》 3 實(shí)體繼承
  4. Python的魔法ORM --《PonyORM教程》 4 高級(jí)定義和連接查詢
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末啥纸,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子婴氮,更是在濱河造成了極大的恐慌斯棒,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件莹妒,死亡現(xiàn)場(chǎng)離奇詭異名船,居然都是意外死亡旨怠,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蜓席,“玉大人,你說(shuō)我怎么就攤上這事雏胃〔t亮!?“怎么了统翩?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵厂汗,是天一觀的道長(zhǎng)娶桦。 經(jīng)常有香客問(wèn)我趟紊,道長(zhǎng)霎匈,這世上最難降的妖魔是什么暖释? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮亮曹,結(jié)果婚禮上照卦,老公的妹妹穿的比我還像新娘。我一直安慰自己瞬痘,他們只是感情好框全,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布克婶。 她就那樣靜靜地躺著,像睡著了一般摹恨。 火紅的嫁衣襯著肌膚如雪晒哄。 梳的紋絲不亂的頭發(fā)上寝凌,一...
    開(kāi)封第一講書(shū)人閱讀 51,182評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音伐债,去河邊找鬼。 笑死双戳,一個(gè)胖子當(dāng)著我的面吹牛千诬,可吹牛的內(nèi)容都是我干的徐绑。 我是一名探鬼主播傲茄,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了山憨?” 一聲冷哼從身側(cè)響起郁竟,我...
    開(kāi)封第一講書(shū)人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎勒虾,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年依溯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片淀弹。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡庆械,死狀恐怖薇溃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情缭乘,我是刑警寧澤沐序,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響策幼,放射性物質(zhì)發(fā)生泄漏邑时。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一垄惧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧绰寞,春花似錦到逊、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至件缸,卻和暖如春铜靶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背他炊。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工争剿, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人痊末。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓蚕苇,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親凿叠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子涩笤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353