使用SQLAlchemy模塊的ORM操作已存在數據庫

之前研究了一段時間的Flask促王,覺得使用ORM操作數據庫真滴爽,于是便去翻了翻SQLAlchemy模塊的文檔唐片。一開始還想著是不是要從table類開始寫污朽,看了一眼數據庫里的一百多張表拦耐,頓時感覺壓力山大......

好在SQLAlchemy可以使用命令生成表類,如下:

# 依賴sqlacodegen模塊
# pip install sqlacodegen -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

# 使用前可以先sqlacodegen –help看一下具體用法

# 一句話生成models.py文件
# sqlacodegen mysql+oursql://user:password@localhost/dbname

# 數據表反向生成sqlalchemy ORM:
# sqlacodegen --tables tablename(表名) --outfile ./filename.py(輸出的文件名) mysql+pymysql://user:password@host/dbname?charset=yourencode

# windows 環(huán)境下cmd窗口 執(zhí)行 即可.(注意輸出的文件)

但這樣操作仍然有些不方便孔轴,尤其是在數據表經常發(fā)生變化的時候,每次都要去同步數據表結構碎捺,感覺就很麻煩路鹰。

雖然數據庫里有一百多張表,但筆者經常用的表也就十多個收厨,總有一種殺雞焉用牛刀的感覺晋柱,個人也還是更喜歡pymysql那樣的連接方式。

好在SQLAlchemy也提供了反射ORM的方法--automap_base诵叁。

from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import Session
from sqlalchemy import create_engine


# 連接url
client_url = f'mysql+pymysql://user:password@host:port/dbname?charset=yourencode'
# 連接引擎
engine = create_engine(client_url, pool_size=10)
# 生成所有的映射關系為Base
Base = automap_base()
# 設置被映射的類和關系并執(zhí)行映射
Base.prepare(engine, reflect=True)
# 獲取會話連接
session = Session(bind=engine)
# 獲取表對象
table = Base.classes.table_name

接下來就可以用ORM方式操作數據庫了雁竞。

# select 全表查詢
datas = session.query(table).all()

# insert 插入記錄
user = table(username='xxx', password='xxx')
session.add(user)
session.commit()

# update 更新記錄
session.query(table).filter_by(username='xxx').update({'password':'xxxxxx'})
session.commit()

# delete 刪除記錄
session.query(table).filter_by(username='xxx').delete()
session.commit()

還可以根據自己的需求進一步封裝api。

首先拧额,先將上述操作寫入到類中碑诉。

class SqlAlchemyScript:
    def __init__(self, host='xx.xx.xx.xx', user='xxxx', passwd='xxxxxx', port=3306, db='xx', charset='UTF8MB4'):
        self.host = host
        self.user = user
        self.passwd = passwd
        self.port = port
        self.db = db
        self.charset = charset
        # 數據庫連接url
        self.client_url = f'mysql+pymysql://{self.user}:{self.passwd}@{self.host}:{self.port}/{self.db}?charset={self.charset}&autocommit=true'
        # 數據庫連接引擎
        self.engine = create_engine(self.client_url, pool_size=5)
        # 生成所有的映射關系為Base
        self.Base = automap_base()
        # 設置被映射的類和關系并執(zhí)行映射
        self.Base.prepare(self.engine, reflect=True)
        # 獲取會話連接
        self.session = Session(bind=self.engine)

在這個類中定義2個獲取表對象的方法。get_table方法獲取單獨的表侥锦,get_tables方法獲取列表中的所有表并返回1個包含所有表對象的列表联贩。

    def get_table(self, table_name):
        """
        獲取表對象
        :param table_name: 表名
        :return: table
        """
        if isinstance(table_name, str):
            strs = f'self.Base.classes.{table_name}'
            # 反射得到ORM
            table = eval(strs)
            return table
        else:
            raise TypeError('傳入的類型必須是str!!!')
    
    def get_tables(self, tables):
        """
        獲取表對象
        :param tables: 存儲表名的列表或元組
        :return: list
        """
        lst = list()
        if isinstance(tables, list) or isinstance(tables, tuple):
            for t in tables:
                table_obj = self.get_table(t)
                lst.append(table_obj)
        else:
            raise TypeError('傳入的類型必須是list or tuple!!!')
        return lst

接下來可以封裝任意你想使用的功能。

比如:定義1個簡單插入方法捎拯。

    def simple_insert(self, table, data_dict):
        """
        插入記錄
        :param table: 表對象
        :param data_dict: 插入的數據(dcit)
        :return: 新插入的實例
        """
        result = table(**data_dict)
        self.session.add(result)
        self.session.commit()
        print(f'{data_dict} 已插入表@峄稀Cぱ帷!')
        return result

使用方法如下:

if __name__ == '__main__':
    test = SqlAlchemyScript()
    table = test.get_table('table_name')
    result = test.simple_insert(table, {'username': 'xxx', 'password': 'xxx'})
    print(f'新插入了1條記錄祸泪,該記錄的id為:{result.id}')
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末吗浩,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子没隘,更是在濱河造成了極大的恐慌懂扼,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件右蒲,死亡現(xiàn)場離奇詭異阀湿,居然都是意外死亡,警方通過查閱死者的電腦和手機瑰妄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進店門陷嘴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人间坐,你說我怎么就攤上這事灾挨。” “怎么了竹宋?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵劳澄,是天一觀的道長。 經常有香客問我蜈七,道長秒拔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任飒硅,我火速辦了婚禮溯警,結果婚禮上,老公的妹妹穿的比我還像新娘狡相。我一直安慰自己梯轻,他們只是感情好,可當我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布尽棕。 她就那樣靜靜地躺著喳挑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪滔悉。 梳的紋絲不亂的頭發(fā)上伊诵,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天,我揣著相機與錄音回官,去河邊找鬼曹宴。 笑死,一個胖子當著我的面吹牛歉提,可吹牛的內容都是我干的笛坦。 我是一名探鬼主播区转,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼版扩!你這毒婦竟也來了废离?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤礁芦,失蹤者是張志新(化名)和其女友劉穎蜻韭,沒想到半個月后,有當地人在樹林里發(fā)現(xiàn)了一具尸體柿扣,經...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡肖方,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了未状。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片俯画。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖娩践,靈堂內的尸體忽然破棺而出活翩,到底是詐尸還是另有隱情烹骨,我是刑警寧澤翻伺,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站沮焕,受9級特大地震影響吨岭,放射性物質發(fā)生泄漏。R本人自食惡果不足惜峦树,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一辣辫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧魁巩,春花似錦急灭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至肾扰,卻和暖如春畴嘶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背集晚。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工窗悯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人偷拔。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓蒋院,卻偏偏與公主長得像亏钩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子悦污,可洞房花燭夜當晚...
    茶點故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內容