python SQLAlcheme ORM 对象关系映射
最近在使用Fastapi编写web接口,涉及mysql数据库了记录一下使用SQLAlcheme: https://www.osgeo.cn/sqlalchemy/orm/tutorial.htmlfrom sqlalchemy import create_enginefrom sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker SQLALCHEMY_DATABASE_URL: str = 'mysql+pymysql://root:123456@127.0.0.1:3306/user?charset=utf8' # 1.生成一个SQLAlchemy引擎 初始化数据库连接: engine = create_engine( SQLALCHEMY_DATABASE_URL, pool_pre_ping=True, echo=True )
# 2.基于数据库引擎生成sessionlocal类,这个类的每一个实例都是一个数据库的会话 注意命名为SessionLocal,与sqlalchemy的session分隔开 SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) # DBSession类型 session = SessionLocal()
# 3.创建一个基类,用来创建数据库中表时使用
Base = declarative_base() # 该基类维护一个与该基相关的类和表的目录-这称为 声明性基类 . 既然我们有了一个“基”,就可以根据它定义任意数量的映射类就可以创建表了
# 4.根据第二步创建的SessionLocal()创建临时会话:我们现在准备开始与数据库对话。ORM对数据库的“句柄”是Session
. 当我们第一次设置应用程序时,与我们的create_engine()
语句,我们定义Session
将用作新工厂的类Session
物体: 就是本文中SessionLocal
session = SessionLocal()
# 5,数据库添加数据
ed_user = User(name='ed',email='tarzan@qq.com',hashed_password='tyuiytouyih@')
# 6.使用数据库会话进行add
session.add(ed_user) # 尚未发出SQL,对象尚未由数据库中的一行表示
ed_user.name = 'tarzan' # 修改
#我们可以增加更多 User
对象同时使用 add_all()
:
session.add_all([
User(name='ed',email='tarzan@qq.com',hashed_password='tyuiytouyih@'),
User(name='ed',email='tarzan@qq.com',hashed_password='tyuiytouyih@')])
# 查看当前事务
session.query(User).filter_by(name='ed').first()
# 7.我们告诉Session
我们希望发布对数据库的所有剩余更改,并提交整个过程中一直在进行的事务。我们这样做通过Session.commit()
. 这个Session
发出UPDATE
“ed”上昵称更改的声明,以及INSERT
两个新的声明User
我们添加的对象:
session.commit()
# 8.回滚
session.rollback()
# 9.查询
for instance in session.query(User).order_by(User.id):
print(instance.name)
for u in session.query(User).order_by(User.id)[1:3]
print(u)
#过滤结果 filter_by()
,使用关键字参数
for name, in session.query(User.name).filter_by(fullname='Ed Jones'):
# 或… filter()
,它使用更灵活的SQL表达式语言构造。这些允许您在映射类上使用具有类级属性的常规python运算符:
for name, in session.query(User.name).filter(User.fullname=='Ed Jones'):
# 这个 Query
对象完全 生成的 ,这意味着大多数方法调用都返回一个新的 Query
对象,在此对象上可以添加其他条件,可以调用 filter()
两次
for user in session.query(User).filter(User.name=='ed').filter(User.fullname=='Ed Jones'):
print(user)
常用筛选器运算符
下面是在 filter()
:
-
query.filter(User.name == 'ed')
-
query.filter(User.name != 'ed')
-
query.filter(User.name.like('%ed%')) # 区分大小写
query.filter(User.name.ilike('%ed%')) # 不区分大小写
-
query.filter(User.name.in_(['ed', 'wendy', 'jack'])) # works with query objects too: query.filter(User.name.in_(session.query(User.name).filter(User.name.like('%ed%')))) # use tuple_() for composite (multi-column) queries from sqlalchemy import tuple_ query.filter( tuple_(User.name, User.nickname).\ in_([('ed', 'edsnickname'), ('wendy', 'windy')]) )
-
query.filter(~User.name.in_(['ed', 'wendy', 'jack']))
-
query.filter(User.name == None) # alternatively, if pep8/linters are a concern query.filter(User.name.is_(None))
-
query.filter(User.name != None) # alternatively, if pep8/linters are a concern query.filter(User.name.is_not(None))
-
AND
::# use and_() from sqlalchemy import and_ query.filter(and_(User.name == 'ed', User.fullname == 'Ed Jones')) # or send multiple expressions to .filter() query.filter(User.name == 'ed', User.fullname == 'Ed Jones') # or chain multiple filter()/filter_by() calls query.filter(User.name == 'ed').filter(User.fullname == 'Ed Jones')
注解
确保使用
and_()
和 not Pythonand
接线员!
-
OR
::from sqlalchemy import or_ query.filter(or_(User.name == 'ed', User.name == 'wendy'))
注解
确保使用
or_()
和 not Pythonor
接线员!
-
query.filter(User.name.match('wendy'))
注解
ColumnOperators.match()
使用特定于数据库的MATCH
或CONTAINS
函数;其行为因后端而异,在某些后端(如sqlite)上不可用。