工作中,使用sqlalchemy自动反射数据库表结构,可以直接获得映射类。表对应的字段都可以直接使用类对象的“.属性”格式获得。
下面是一个简单的例子:
from sqlalchemy import create_engine, inspect, MetaData
from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import sessionmaker
import pymysql
pymysql.install_as_MySQLdb()
url = 'mysql+mysqldb://root:123456@127.0.0.1/mylocal_db'
tables = ['sf_order']
class DBUser:
def __init__(self):
engine = create_engine(url)
metadata = MetaData()
metadata.reflect(bind=engine, only=tables)
Base = automap_base(metadata=metadata)
Base.prepare()
self.sf = Base.classes.sf_order
# self.sf.__repr__ = __repr__
self.Session = sessionmaker(bind=engine)
def get_one_order(self):
"""
取出表中的第一个数据
"""
session = self.Session()
order = session.query(self.sf).limit(1).first()
session.close()
return order
db = DBUser()
if __name__ == '__main__':
order1 = db.get_one_order()
print(order1)
print(order1.sf_id)
运行结果
<sqlalchemy.ext.automap.sf_order object at 0x000001E502B6D7C8>
1
看见order.sf_id
可以直接获得对应的sf_id字段的内容,但是直接print
取出行数据的对象,只能获得内存地址。可见,sqlalchemy并没有给自动映射类添加__repr__
方法。
我们可以手动添加一下。
class DBUser:
def __init__(self):
engine = create_engine(url)
metadata = MetaData()
metadata.reflect(bind=engine, only=tables)
Base = automap_base(metadata=metadata)
Base.prepare()
# 做一个自定义的 __repr__
# 注意配合 sqlalchemy 模块的 inspect方法,获取映射类的属性
def __repr__(self_):
ret = f'{type(self_).__name__}<'
for key in inspect(type(self_)).c.keys():
ret += f'{key}: {getattr(self_, key)},'
ret.rstrip(',')
ret += '>'
return ret
self.sf = Base.classes.sf_order
# 如果将多张表映射了动态类,这边可以按相同格式处理
self.sf.__repr__ = __repr__
self.Session = sessionmaker(bind=engine)
def get_one_order(self):
session = self.Session()
order = session.query(self.sf).limit(1).first()
session.close()
return order
db = DBUser()
if __name__ == '__main__':
order1 = db.get_one_order()
print(order1)
print(order1.sf_id)
输出:
sf_order<sf_id: 1,bill_no: SF20230427002,from_address: 兴业大厦887,>
1