使用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 环境下cmd窗口 执行 即可.(注意输出的文件)

但这样操作仍然有些不方便,尤其是在数据表经常发生变化的时候,每次都要去同步数据表结构,感觉就很麻烦。

虽然数据库里有一百多张表,但笔者经常用的表也就十多个,总有一种杀鸡焉用牛刀的感觉,个人也还是更喜欢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()
# 设置被映射的类和关系并执行映射
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()
        # 设置被映射的类和关系并执行映射
        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} 已插入表!!!')
        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}')

你可能感兴趣的:(使用SQLAlchemy模块的ORM操作已存在数据库)