亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

經驗拾憶(純手工)=> Python-ORM之peewee:插件拓展(三)

系統 1598 0

聲明

本篇主要講,關于peewee的一些拓展:
包括新式CRUD-數據導入導出-信號-數據庫反向生成模型。
擴展官檔:http://docs.peewee-orm.com/en...

作者友好 與 peewee提問方式

當我用到拓展模塊的 新CRUD時,文檔給的內容少之又少。
因為拓展的新CRUD是真的方便好用,和(PyMongo的用法差不多)
但是功能卻不全。并且與我們第二篇,講的CRUD又不兼容。
所以在難以取舍之際, 我選擇了提問。

peewee作者在官檔中詳細說到。 如果你有問題或疑惑可以通過以下兩種方式:

  1. 去stack overflow 提問題,標簽打上python 和 peewee。 peewee作者會不定期瀏覽并回答你給你幫助。
  2. 去https://groups.google.com/gro...,這個google群組提問。(需要科學上網)

所以我選擇了去 stack overflow提問。

我問題發出去,應該是不到一小時,作者就給回復了,我驚了。。(發完我就睡覺了,第二天起來才看到)
提問內容傳送門如下:https://stackoverflow.com/que...

作者回復的意思是:

拓展的playhouse.dataset里面的DataSet 的 新式CRUD API 的涉及初衷就是為了簡單使用。
但它并不會代替 核心CRUD (就是我們第二篇講的CRUD)
并且,它設計的初衷就是讓我們可以方便 (json/csv格式的數據 與 數據庫的數據 相互導入或導出)
我說的這些操作,下面都會寫到。

所以說,該提問就提問,你收獲了peewee知識的同時,又能增加peewee的社區活躍度。

playhouse擴展模塊的DataSet

我們前2篇文章就用了這一行代碼就可以導入所有,因為所有基本功能都集成在 peewee下

          
            from peewee import *
          
        

但接下來講的是擴展,而擴展就是新分支了,與peewee沒關系了

          
            from playhouse.dataset import DataSet

          
        

數據庫連接

進入正題,連接MySQL,你可以有兩種連接方式:

          
            # 強調一下,官檔中給出 DataSet 是在 playhouse.dataset 下
# 我再強調一下, 是 DataSet , 而不是 DataBase  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
from playhouse.dataset import DataSet
db = DataSet('mysql://root:Jilin963389970@39.107.86.223:3306/test')

          
        

官檔-所有數據庫的連接示例: http://docs.peewee-orm.com/en...

數據庫與表的基本操作

創建表

          
            owner = db['owner']
# 后面這個"owner" 是你自己指定的key, 也就是你指定的 "表名"
# 前面這個 owner 變量用來接受返回結果,它就是一個實例化的表對象。 一會我們用它做一系列操作

我講完了,表已經創建好了,  (你臉上有沒有出現問號。。) 驚不驚喜,意不意外??
題外話:
    如果你用過,pymongo來使用MongoDB, 那這種原理應該不陌生的。
 
那 owner = db['owner']     這一行代碼究竟做了什么?
    1. 它會去數據庫,創建一個 名為 owner的表 (有則返回,無則創建)
    2. 不但創建了表, 而且它還在表中 自動創建了一個 id  (int型,主鍵,自增)

          
        

列出表 & 列出字段

列出表(等價于MySQL中的命令: show tables)

          
            print(db.tables)  
>> ['new_owner', 'owner']
          
        

列出表中的字段(等價于MySQL中的命令: show columns):

          
            table = db['owner']        # 先選擇一個表。
print(table.columns)
>> ['id', 'name', 'age', 'gender', 'hobby', 'nickname']
          
        

統計表中記錄數(就是行數)

          
            print(len(table))
>> 10
          
        

事務(transaction)

其實我在第一篇,已經講過事務了
事務-傳送門: https://segmentfault.com/a/11...

          
            當時我是用的 MySQLDatabase 連接工具。 
    我只講了一種使用方法:  db.atomic()
    其實還有另外一種使用方法,就是  db.transaction()
    這兩種方法差不多, 你可以這么認為,就是把 atomic 和 transaction 單詞換一下,用法一模一樣

而現在我們是使用的 DataSet 連接工具 (開篇我強調過):
    db = DataSet(....)   
    DataSet 只提供給我們   transaction()這種用法, 而沒有提供 atomic()
    
但我說了,這兩種用法你可以認為只是單詞換了一下。用法一樣的。
因此你完全可以直接看我前面給的 "事務-傳送門" 這篇之前寫的文章。  
          
        

CRUD (這種CRUD方式我不太推薦)

  1. 我們第二章詳細講過全套的CRUD,其實那就夠了。
  2. 而本章這個拓展的CRUD,完全是另一種模式。另一個模塊的東西。
  3. 但我不推薦用,因為感覺還沒成熟,不完善(很多CRUD細節功能沒有), 官檔給的也粗略。
  4. 此外,下面涉及到與 本套CRUD有關聯的操作, 我下面統稱為 "拓展的CRUD"

增加數據

          
            owner.insert(name='Alice', age=20)
owner.insert(name='Zhang', age=18)

這看起來沒什么問題,我們之前講的差不多。但你有沒有意識到幾個問題:
1. owner表 是自動創建出來的,它只有一個主鍵。
2. 我們沒有創建 name 和 age 字段
3. 既然沒有創建字段,為什么可以插入數據???

解惑:
    1. 我們調用第一個 insert()的時候, 它就會自動幫我們 去數據庫創建對應參數的字段(固定了):
       數據類型關系對照如下:
           python數據類型  MySQL數據類型
               int            int(11)     允許為空   默認值未空
               str            text        允許為空   默認值未空
        那peewee為我們自動創建的字段如下:
        +-------+---------+------+-----+---------+----------------+
        | Field | Type    | Null | Key | Default | Extra          |
        +-------+---------+------+-----+---------+----------------+
        | id    | int(11) | NO   | PRI | NULL    | auto_increment |
        | name  | text    | YES  |     | NULL    |                |
        | age   | int(11) | YES  |     | NULL    |                |
        +-------+---------+------+-----+---------+----------------+
    2. 創建后,它還會自動為我們根據我們傳的參數, 對應的插入 值
    3. 特別注意,特別注意:
        假如我們插入這樣一條錯誤"類型"的數據: 
            owner.insert(name=18, age=18)    # 按理說name應該為 text型,age應該為整形
            雖然我們name給的整形,但,peewee內部會自動為我們轉為將 name轉為字符串類型
            同理 字符串也會自動幫我們轉為整形(對應數據庫中的類型)。 但'abc'這樣的轉不了哦
          
        

修改數據

          
            owner.update(name='Alice',  age='50')
這行代碼為我們做了如下事情:
    將"所有"行數據, name改為 Alice, age改為 50
    
owner.update(name='Alice',  age='50',columns=['name'])
多加了一個 columns參數,為我們做了如下事情:
    先看最后的 columns=['name']  : 其實他就等價于  where name = xxx
    其實意思就是以 "name字段為條件" 修改數據:(而name我們已經給了 = 'Alice')
    具體過程如下:
        1. 找到 name = Alice, 的所有記錄
        2. 將 name= Alice 的記錄   name改為Alice(相當于沒變), age 改為 50

owner.update(gender='man')
    你仔細看看,我們之前是沒有 gender這個字段的。 如果更新未創建字段,它會為我們做如下事情:
    1. 它會自動為我們在這個表中創建一個 這個 "gender新字段"
    2. 并且,"所有行記錄" 都會被賦予成 "man" 值。 注意是 所有行,所有行,所有行
    
    3. 如果你只想"給指定記錄部分"賦予 "man"值, 那你可以加一個我們之前說的 "columns參數"
       自然而然地,其他 "未通過 columns指定的記錄" 就會被賦予 NULL 值。
          
        

查詢數據

首先說一下它這個查詢的特色。

  1. 可以對查詢結果進行 切片,索引操作(和python的切片和索引是一模一樣的)
  2. 索引之后自動轉為 列表嵌字典 [{}, {}]
  3. 下面3種方式,也都支持 切片和索引(我就不舉例了,很簡單)

方式1:all() 獲取全部數據

          
            owner = db1['owner']
query = owner.all()
for obj in query:
    print(obj)        # 遍歷每條記錄, 結果是 字典 類型
          
        

方式2:find() 查詢符合條件的所有數據

          
            query = owner.find(name='Tom')   # 查詢名為 Tom的數據
for obj in query:
    print(obj)        # 遍歷每條記錄, 結果是 字典 類型
          
        

方式3:find_one() 查詢符合條件的 第一條 數據

          
            print(owner.find_one(name='Tom'))

注意一下,find_one 查出來結果就是一條字典。  不要再遍歷了,遍歷就出事了。。。
          
        

刪除數據

          
            result = owner.delete(name='Tom')
 
說明:
    1. 若 delete() 不指定參數,那么即為全部刪除。。慎用
    2. 返回值result的值, 代表刪除數據的條數


          
        

Json/CSV數據 導入到數據庫(只能聯用拓展的CRUD)

Json實例

我在當前目錄下創建一個 new_owner.json, 內容如下:

          
            [
  {"name": "Alice", "age": 18},        
  {"name": "Zhang", "age": 30}
]
          
        

主文件代碼如下:

          
            new_owner = db['new_owner']    # 新建一張表,名為 new_owner
new_owner.thaw(
    filename='new_owner.json',   # 就是上面的那個 json文件
    format='json'                # 指定格式為json, 默認值是 csv
)
這樣就導入好了,數據庫內容如下:
    +----+------+-------+
    | id | age  | name  |
    +----+------+-------+
    |  1 |   18 | Alice |
    |  2 |   30 | Zhang |
    +----+------+-------+
          
        

特殊情況分析: 假如基于上面創建好的數據庫與數據, 將剛剛的json文件稍加改動,加個 "gender"

          
            [
  {"name": "Alice", "age": 18, "gender": "man"},  
  {"name": "Zhang", "age": 30}
]
          
        

假如我們還是用上面的一模一樣的主文件代碼(我這里就不重復寫了),導入剛修改的 新json數據。

          
            我們分析一下:
    我說了,是在原有表 和 字段的 基礎上去導入新數據。 (原有數據庫字段為 name 和 age)
    但是今時不同往日。。。  我們剛剛的json新添加了一個, gender。
    而原有的數據庫中,并沒有這個字段。 如果我們還是用之前的這個代碼:
    new_owner.thaw(
        filename='new_owner.json',   # 就是上面的那個 json文件
        format='json'                # 指定格式為json, 默認值是 csv
    )
    那么,peewee會自動把這個 新 gender 鍵,同步到數據庫,并生成 新字段 gender
        +----+------+-------+--------+
        | id | age  | name  | gender |
        +----+------+-------+--------+
        |  1 |   18 | Alice | NULL   |
        |  2 |   30 | Zhang | NULL   |
        |  3 |   18 | Alice | man    |
        |  4 |   30 | Zhang | NULL   |
        +----+------+-------+--------+    看見了把,gender字段,會自動生成。

          
        

但是在某種情況下, 你并不想讓數據庫 創建這個 新字段
假如json中 "gender" , 它屬于一個臟數據,我們不需要他,而是單純的想插入 name和age數據。
那么你可以,添加一個 strict=True 參數:

          
            new_owner.thaw(
    filename='new_owner.json',  
    format='json',               
    strict=True                # 看這里,添加一個這個 strict=True就好了
)

strict=True意味著,它會對照json的key 與 數據庫的字段, 并以數據庫的字段為主,嚴格匹配插入。
          
        

CSV示例

其實和json的幾乎差不多,注意csv格式,逗號分隔,設置表頭。 new_owner.csv 內容如下:

          
            name,age
Alice,18
Zhang,30
          
        

主文件代碼如下

          
            new_owner.thaw(
    filename='owner.csv',
    # format='csv'         # 我說過,format默認參數就是csv,所以給不給format參數都行。
    # strict=True          # 嚴格匹配字段插入, 和上面講的json是一模一樣的作用。
)
          
        

最后說個小細節,不知道你有沒有注意,我們json和csv文件, 都沒有指定id。
雖然沒有指定,但是 peewee 同樣會為我們自動創建 id (同樣也是 int(11), 主鍵, 自增)

數據庫數據導入到Json/CSV(只能聯用拓展的CRUD)

導入都說完了,導出就更簡單了。。就API變個名的事:
導出單個表的全部數據:

          
            owner = db['owner']

owner.freeze(
    filename='new_owner.json',  
    format='json',  # 指定格式為json,   你要是不指定,默認值是 csv
)
          
        

當然,這里有個特色,導出方式還可以 導出某個查詢結果!!

          
            query = owner.find(name='Tom')
db.freeze(
    query,                      # 查詢結果,注意這個查詢結果,必須是個查詢集類型。
    filename='new_owner.json', 
    format='json',  # 指定格式為json,   你要是不指定,默認值是 csv
)
          
        

中場暫停。。。

至此,playhouse.dataset的DataSet里面的 新版CRUD,及其附屬功能(json導入導出等)講完。
也許你會很不適應。 (這新版的CRUD,如果實在不能掌握,就當了解即可)

最重要的還是第二篇文章的CRUD:https://segmentfault.com/a/11...
以下要講的,就是 第二篇文章講的,正常的 (from peewee import * )里面的 CRUD 相關的操作了。

信號(Signal)

官方只設定了如下 4 種信號:
一、pre_save: 保存之前調用
二、post_save:保存之后調用

          
            pre_save 和 post_save只支持下面兩種API:
1. create()  # 創建數據
觸發:
    Owner.create(name='Tom')  # create包含了 save() ,所以會自動觸發
2. save()    # 更新數據
觸發:
    obj = Owner.get(name='Butch')
    obj.name = 'Alice'
    obj.save()
注意: 你想用保存信號,就必須用這兩種API,  用 update()是不好使的哦!!!!!!!!!!
          
        

三、pre_delete: 刪除數據之前調用
四、post_delete:刪除數據之后調用

          
            pre_delete 和 post_delete 只支持一種 API ,那就是  delete_instance()
觸發:
    objs = Owner.select().where(Owner.name=='lin')
    for obj in objs:
        obj.delete_instance()

          
        

接下來我們開始看代碼如何寫:
先把表和數據構造出來,還是老方式:

          
            from peewee import *

# 注意是 playhouse里的Model, 以及前面提到的 4 種 信號
from playhouse.signals import Model, post_save, pre_save, pre_delete, post_delete    


db = MySQLDatabase('test', user='root', password='123',
               host='IP', port=3306, charset='utf8mb4')
               
class Owner(Model):        
"""
    特別注意,這個Model, 使用是playhouse.signals下的 Model
    而不是 peewee 下的 Model, 這需要特別注意
    兩個模塊都有Model, 所以把用的Model放在 相對偏下面導入 
"""
                             
    data = IntegerField()    # 而字段依然是 from peewee import * 導入的
    class Meta:
        database=db
db.create_tables([Owner])
          
        

進入正題:信號使用有兩種方式:
方式1(裝飾器方式):

          
            # 前面的4種信號的用法就是用來,裝飾一個自定義函數。
# 這個自定義函數就是信號出發之后,為我們做事的。
# 接下來我以 post_save 為例 (當然我這個例子只是強調一下語法,并沒有實用價值)

@pre_save(sender=Owner)  # sender指定 我們的模型類
def aaa(model_class, instance, created=True):  # 這個名字隨便起
    """
        model_class:   就是 Owner這個類,默認傳進來方便你使用
        instance 和 create=True 照著寫上就行不用管它
    """
    print(f"數據入庫之前我們捕獲了此表名=>{model_class}")
    for obj in model_class.select().dicts():   # model_class就是Owner類,它可以任意CRUD
        print(f"再次查看此表信息{obj}")

觸發信號:
obj = Owner.get(name='Tom')
obj.name = 'Rose'
obj.save()

          
        

方式2 (函數連接):
信號-官檔:http://docs.peewee-orm.com/en...
其實你用 方式1 就行了。

數據庫反向生成 Python模型類

參數官檔:http://docs.peewee-orm.com/en...
看好參數大小寫就行(test是我的數據庫名):

          
            python -m pwiz -e mysql -H 192.6.6.6 -p 3306 -u root -P test > mymodel.py
# 指定了 -P ,密碼是后續命令行 追入的。
          
        

模型遷移 migration

我沒怎么看,需要的自己瞅瞅。。
模型遷移-官檔:http://docs.peewee-orm.com/en...

結束語

其實ORM都差不多。
Django:的ORM還算可以。但是不太好脫離框架單獨使用 (相當于與Django平級)。
sqlalchemy:沒怎么用過。之前看過幾眼。感覺極度不適。感覺學習成本有點高(相當于與Python平級)
peewee:是一個可單獨使用的簡便的ORM框架(寫web爬蟲之類的都能用得上,相當于與Python平級)

我感覺:如果ORM的學習成本大于SQL的學習成本, 那倒不如精修一下SQL,即使換了環境也能用得上。
有時候高階ORM用多了,可能連SQL都不會寫了。。。 (It's just for me......)

第一篇傳送門:https://segmentfault.com/a/11...
第二篇傳送門:https://segmentfault.com/a/11...


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

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

【本文對您有幫助就好】

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

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 亚洲欧洲日本在线观看 | 欧美成人鲁丝片在线观看 | 视频在线欧美 | 国内精品久久久久影院亚洲 | 亚洲成色综合一区二区三区四区 | 亚洲人体视频 | 深夜福利视频网址 | 草草影视在线观看 | 久久综合香蕉 | 乱色专区 | 四虎国产永久在线精品免费观看 | 最新亚洲情黄在线网站 | 国产午夜永久福利视频在线观看 | 国产一区二区精品在线观看 | 操操免费视频 | 久久99视频精品 | 神马影院我不卡在线观看 | 在线观看国产精品入口 | 亚洲一成人毛片 | 日韩欧美视频一区 | 日本免费黄色小视频 | 天天在线欧美精品免费看 | 亚洲国产精品成人综合色在线婷婷 | 欧美日韩在线成人免费视频大全 | 日韩新片王| 91久久精品国产亚洲 | 国产精品国产国产aⅴ | 久久免费大片 | 免费福利入口在线观看 | www.色人阁.com | 草草国产成人免费视频 | 永久黄网站色视频免费观看 | 久草视频在线播放 | 亚洲国产精久久小蝌蚪 | 天天综合网天天做天天受 | 久久浮力影院 | 亚洲另在线日韩综合色 | 韩国精品videosex性韩国 | 99精品国产兔费观看久久99 | 特级毛片免费视频 | 99久久99热久久 |