日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

經(jīng)驗(yàn)拾憶(純手工)=> Python-ORM之peewee:模型-字段-索引

系統(tǒng) 1720 0

前言

去github搜 "python orm",最高star居然不是sqlalchemy,而是peewee
后來得知peewee,比sqlalchemy簡(jiǎn)單好用。值得一學(xué)哦!!
我總體感覺(peewee像 Django-ORM的分離版,,但比Django-ORM和SqlAlchemy 小巧,簡(jiǎn)單,文檔也友好)

還有一個(gè)更重要的感覺就是, peewee 的 API方法名 和 SQL語(yǔ)句 的 單詞 基本相似。
例如對(duì)比一下(關(guān)鍵詞語(yǔ)法都是 update 和 where):

          
            SQL語(yǔ)句:update Lang set name='Python' where name='Java';
Peewee:Lang.update(name='Python').where(Lang.name == 'Java')
          
        

這種良心的API,可以大大降低我們的學(xué)習(xí)成本,還可以鞏固我們對(duì)SQL的記憶!!!!!!
總官檔地址:http://docs.peewee-orm.com/en...
官方Github地址:https://github.com/coleifer/p...

安裝和導(dǎo)入

          
            pip install peewee
from peewee import *
# peewee的模塊很結(jié)構(gòu)化,都在peewee中,如果懶就都導(dǎo)入進(jìn)來。 當(dāng)然你也可以熟了,按需導(dǎo)入
# 后面無特殊情況,就都是這樣導(dǎo)入的。我就不提了。
          
        

數(shù)據(jù)庫(kù)

postgresql 和 sqlite

peewee 只支持 sqlite, mysql 和 postgresql 數(shù)據(jù)庫(kù), 如果你有需求用oracle等,請(qǐng)繞行。。。
如需sqlite 和 postgresql,配置請(qǐng)參考 http://docs.peewee-orm.com/en...

mysql

當(dāng)然我經(jīng)常用MySQL,以后的所有都圍繞mysql來講,如下是基本配置

          
            mysql_db = MySQLDatabase(
    'lin',                 # 數(shù)據(jù)庫(kù)
    user='root',           # 用戶名
    password='123',        # 密碼
    host='IP',             # IP
    port=3306,             # 端口
    charset='utf8mb4'      # 字符集類型, utf8mb4 是 utf8的大哥
)
          
        

peewee的mysql引擎默認(rèn)優(yōu)先使用pymysql。
如果你沒安裝pymysql, 他就會(huì)去尋找 MySQLdb。 都沒有就會(huì)報(bào)錯(cuò)。
嗯,都啥年代了,python3的時(shí)代,所以我們用 pymysql模塊即可,若沒安裝,跳出來安裝下即可

          
            pip install pymysql
          
        

既然用的pymysql驅(qū)動(dòng),MySQLDatabase() 里面的寫法 和 pymysql對(duì)象實(shí)例化的參數(shù)配置是一樣的。
如果我給的例子的參數(shù)不夠用,你可以來下面的鏈接自己選吧:https://github.com/PyMySQL/Py...

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

          
            print(mysql_db.connect())
          
        

關(guān)閉數(shù)據(jù)庫(kù)連接

          
            print(mysql_db.close())
          
        

測(cè)試數(shù)據(jù)庫(kù)連接是否關(guān)閉

          
            mysql_db.is_closed()
          
        

列出數(shù)據(jù)庫(kù)的所有表:

          
            mysql_db.get_tables()   
          
        

列出所有字段的詳細(xì)信息:

          
            print(db.get_columns('owner'))    # 假設(shè) owner是表名,下面同理
          
        

列出所有主鍵的字段:

          
            print(db.get_primary_keys('owner'))
          
        

列出所有索引字段的詳細(xì)信息:

          
            print(db.get_indexes('owner'))
          
        

列出所有外鍵的字段:

          
            print(db.get_foreign_keys('owner'))

          
        

Python 各種 web框架嵌入使用 peewee 案例傳送門:
官檔-Web案例:http://docs.peewee-orm.com/en...

表-記錄-字段

ORM語(yǔ)法 和 數(shù)據(jù)庫(kù)的 (表-記錄-字段)對(duì)應(yīng)關(guān)系如下:

ORM結(jié)構(gòu) 數(shù)據(jù)庫(kù)
實(shí)例(對(duì)象) 記錄
類屬性

默認(rèn)自增主鍵ID

定義一個(gè)類,繼承了peewee模塊的Model類,這個(gè)類就可以當(dāng)作Model來用了
首先建立一張"空表"

          
            mysql_db = MySQLDatabase('lin_test', user='root', password='123',
                     host='ip', port=3306, charset='utf8mb4')
class Owner(Model):
    class Meta:             
        database=mysql_db   # 這里是"必須" 要指定的, 指定哪一數(shù)據(jù)庫(kù)
mysql_db.create_tables([Owner])    # 注意,源碼是取出參數(shù)遍歷,所以這里參數(shù)用列表
          
        

上述代碼就可以建立一張"空表"。 為什么"空表" 用引號(hào)括起來呢??

          
            這是關(guān)于peewee orm的機(jī)制,"你若不指定(primary key)",它就會(huì)"自動(dòng)"為你創(chuàng)建一個(gè)
"名為 id", "類型為 int", 并設(shè)置為 "primary" 的 "自增(auto_increment)" 的字段
          
        

但 一旦你把一個(gè)自定義的字段,設(shè)為主鍵,默認(rèn)的id字段就會(huì)被覆蓋:

          
            name = CharField(primary_key=True)   # name設(shè)為了主鍵, 原有的默認(rèn)id就沒了 
          
        

官檔也說明:如果你想自己建立一個(gè)自增主鍵,并覆蓋默認(rèn)id。你可以用AutoField字段:

          
            new_id = AutoField()    # 這句話直接就為你 設(shè)置為 int型 和 主鍵 和自增。 
"這是官檔最推薦覆蓋id的方法,  而不是自己弄一個(gè) Integer,再設(shè)主鍵"

          
        

自增id就講完了, 不過你是否發(fā)現(xiàn)每個(gè) 類下都有

          
            class Meta:
    database= xxx   # 這是為每張表指定數(shù)據(jù)庫(kù),必須要指定的。不然它不知道你這個(gè)表在哪個(gè)數(shù)據(jù)庫(kù)
          
        

既然這樣,若我們要在一個(gè)數(shù)據(jù)庫(kù)中創(chuàng)建很多很多表,那豈不是每次都需要給每張表指定一個(gè)數(shù)據(jù)庫(kù)??
就像這樣:

          
            class User(Model):
    class Meta:
        database = mysql_db

class Owner(Model):
    class Meta:
        database = mysql_db
          
        

這樣有點(diǎn)煩,但我們可以定義一個(gè)基類指定好數(shù)據(jù)庫(kù), 然后其他子類模型繼承它就好了。

          
            class BaseModel(Model):
    name = CharField(max_length=10)    # 定義一個(gè) name 字段
    class Meta:
        database = mysql_db
        
class User(BaseModel):    # 繼承基類
    pass
class Owner(BaseModel):   # 繼承基類
    pass
    
mysql_db.create_tables([User, Owner])    # 正式創(chuàng)建表, 基類不需要,可以不放進(jìn)來
          
        

像上述代碼CharField, 更多類型字段定義,官檔給的很詳細(xì)了,我不再贅述了。
官檔-字段-參數(shù):http://docs.peewee-orm.com/en...
但下面我還會(huì)挑一些主要常用(有一點(diǎn)點(diǎn)點(diǎn)難特別)的說一下。。。

外鍵字段(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',  # 通過引用名獲取對(duì)象。"主人,你可以通過這個(gè)名字調(diào)用我"
        on_delete='Cascade',   # 級(jí)聯(lián)刪除
            # 默認(rèn)為None, 這時(shí),你想刪主人是刪不掉的。會(huì)報(bào)錯(cuò)。 必須先刪寵物再刪主人。
            # 設(shè)為 Cascade后, 你可以直接刪主人。 他的寵物也會(huì)隨之自動(dòng)刪除。 這就是級(jí)聯(lián)刪除
        on_update=Cascade,     # 級(jí)聯(lián)更新,原理同 on_delete
    )
          
        

層級(jí)外鍵(通常用于層級(jí)分類,自關(guān)聯(lián)查詢):

          
            class Category(BaseModel):
    name = CharField()
    parent = ForeignKeyField('self', null=True, backref='children') 
    注: "self" 字符串是固定語(yǔ)法, 下一篇還會(huì)將,自關(guān)聯(lián)查詢
          
        

日期字段(DateTimeField)

          
            import datetime
......
date_time= DateTimeField(default=datetime.datetime.now) 
          
        

表屬性(Meta)

表屬性就是可以 改表名,設(shè)置主鍵,聯(lián)合主鍵,設(shè)置索引,聯(lián)合索引等操作。不再贅述,見官檔。
官檔 Meta: http://docs.peewee-orm.com/en...

索引 和 約束

設(shè)置索引有3種方法:

  1. 通過定義字段的參數(shù):
    普通索引

                  
                    name = CharField(index=True)
                  
                

    唯一索引

                  
                    name = CharField(unique=True)
                  
                
  2. 通過定義表屬性Meta:
    聯(lián)合唯一索引

                  
                    class Meta:
        indexes = (
            (('字段1', '字段2'), True),    # 字段1與字段2整體作為索引,True 代表唯一索引
            (('字段1', '字段2'), False),   # 字段1與字段2整體作為索引,F(xiàn)alse 代表普通索引
        )
    需要注意的是,上面語(yǔ)法,三層元組嵌套, 元組你懂得, 一個(gè)元素時(shí)需要加個(gè) , 逗號(hào)。 別忘了。
                  
                
  3. 索引API:
    官檔:http://docs.peewee-orm.com/en...

設(shè)置約束有2種方法:

  1. 通過定義字段的參數(shù):
    -------通常用來單一字段主鍵:

                  
                    name = CharField(primary_key=True)
                  
                
  2. 通過定義表屬性Meta
    -------通常用作聯(lián)合主鍵:

                  
                    class Meta:
        primary_key = CompositeKey('字段1', '字段2')
        # primary_key = False      # 也可以不使用主鍵(不覆蓋,也 取消 創(chuàng)建默認(rèn)id字段)
    
                  
                

事務(wù)

支持with上下文語(yǔ)法,支持事務(wù)嵌套,注意嵌套事務(wù) 只會(huì)回滾 離它最近 的一層之間的代碼。
包裹在with語(yǔ)句中的代碼,只要存在異常,就會(huì)回滾。嵌套的事務(wù),也是有一處異常,所有層事務(wù)都會(huì)回滾。
當(dāng)然你也可以手動(dòng) rollback()來回滾。
嵌套事務(wù)示例如下:

          
            with mysql_db.atomic() as transaction1:    # 第一層事務(wù)。  atomic(), 固定語(yǔ)法就不說了。 
    User.create(username='Tom')
    with mysql_db.atomic() as transaction2: # 第二層事務(wù)
        User.create(username='Jerry')
        User.create(username='Spike')
        transaction2.rollback()            # 就近原則, 第二層的rollback()回滾
    User.create(username='Butch')
    
# 如果真的出現(xiàn)回滾,那么 從 第二層的 with() 開始算 事務(wù)內(nèi)容, 到 rollback() 結(jié)束
#     形象例子: 頂部 面包片從 第二層的with()開始夾,  底部 面包片 夾到 rollback()

# 注意一點(diǎn),雖然是嵌套事務(wù),但是每層with事務(wù)都有對(duì)應(yīng)的名字(就是with as 之后變量)。 
# 所以回滾寫在哪層事務(wù)里面, 就要用哪層事務(wù)的名字(就近原則)。 不然會(huì)報(bào)錯(cuò)的。
# 錯(cuò)誤實(shí)例: 倒數(shù)第二行的: transaction2.rollback()  寫成 transaction1.rollback()。 錯(cuò)誤!
          
        

帶有commit()的嵌套事務(wù)示例如下:(縮小事務(wù)的代碼范圍, 就像 "面包里夾的東西變少了" 的意思)

          
            with mysql_db.atomic() as transaction1:      # 第一層事務(wù)
    User.create(username='Tom')
    with mysql_db.atomic() as transaction2:  # 第二層事務(wù)
        User.create(username='Jerry')
        transaction2.commit()                # 就這里變了, 插入了一行 commit
        User.create(username='Spike')
        transaction2.rollback()  # rollback()回滾
    User.create(username='Butch')

# commit(),加入了這一行,就意味著 從 這行開始算 回滾內(nèi)容,到 rollback() 結(jié)束
#     形象例子: (頂部 面包片 從commit() 這里開始夾, 底部 面包片 夾到 rollback() )
          
        

上面無論哪個(gè)事務(wù)例子, 都必須注意:

  1. 每層事務(wù),只管自己層內(nèi)的 rollback(),才有效, 不能管其他層的。
  2. 就算你用 commit() 夾, 如果自己層內(nèi)沒有 rollback(), 那么你的 commit()是無效的(夾不住)

事務(wù)就差不多這些,官檔還有一些用法和語(yǔ)法,但最終功能結(jié)果都是一樣的。選一種(我的例子)就行。
官檔-事務(wù): http://docs.peewee-orm.com/en...

閑雜用法

查看ORM對(duì)應(yīng)的原生SQL語(yǔ)句:

          
            .....ORM語(yǔ)句.sql()       # 后綴 .sql() 打印對(duì)應(yīng)原生sql
          
        

執(zhí)行原生SQL:

          
            # 注意,傳數(shù)據(jù)用參數(shù),不要用字符串拼接(防SQL注入)
for owner in Owner.raw('select * from owner where name=%s', 'Alice'):
    print(owner.name)

          
        

更原生的執(zhí)行原生SQL:

          
            print(mysql_db.execute_sql('select * from user').fetchall())
# sql,可以傳位置參數(shù)(防注入),就像使用 pymysql一樣。
          
        

表改名:

          
            注:我說的改名只是查詢時(shí)的臨時(shí)名

下一篇文章查詢,會(huì)提到 字段改名, 格式:  字段.alias('新字段名')
那表改名也差不多,有2種方式:
    方式1:
        格式: 表類.alias('新表名')
    方式2:
        格式: 新表名 = 表類.alias()
          
        

未結(jié)束語(yǔ)

本篇寫了一些入門性的模型的建立,數(shù)據(jù)庫(kù),事務(wù),索引,算是比較基本的。
當(dāng)然還有更常用,更重要的CRUD等,會(huì)在下一篇介紹。
下一篇傳送門:https://segmentfault.com/a/11...


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 桂平市| 和静县| 红安县| 商河县| 泸西县| 涿州市| 乳山市| 苍南县| 宽城| 桂东县| 武乡县| 两当县| 平武县| 苏尼特右旗| 黄龙县| 巫山县| 云林县| 厦门市| 贺州市| 罗城| 邓州市| 禄丰县| 汉阴县| 达尔| 宜兰市| 长子县| 颍上县| 洛宁县| 德格县| 德钦县| 仙桃市| 安吉县| 五大连池市| 韶山市| 肥东县| 岢岚县| 仪陇县| 台州市| 察隅县| 濉溪县| 资阳市|