由于SQLAlchemy 中文资料比较少,所以根据官网给的tutorial外加其他大佬写的中文资料整合以后准备写一个SQLAlchemy 系列的基础入门教程。本系列可能会夹杂一些个人对于python 、SQLAlchemy 以及ORM的理解,如有出错部分,请指正我。
版本信息:
- SQLAlchemy 1.2.15
- Python 3.6+
- Mac OS 10.14
- DB基于SQLite
前序文章Python SQLAlchemy ORM教程(1)讲了怎么建立你数据库,插入数据,也讲了engine和session的相关概念,接下来我们开始看看怎么花式取数据
Querying
SQLAlchemy的官方教程说,你的任何查询都是基于session
的,是session
提供的方法,你需要通过session
的query()
方法生成一个query
对象。query()
是必须传入一个参数的,这是参数可以是一个combination of class
或者 calss-instrumented descriptors
instrumented
关于 combination of class
可以简单理解为类,可能class-instructmented descriptors
比较容易让人发懵,
instrumentations
是将属性附加到类的一个过程,也可以叫Python Descriptors
我们来看一些例子:
#__get__
myobject.someattribut
#__set__
myobject.someattribut = "foo"
#__del__
del myobject.someattribut
以上的行为都可以称为 instrumentation
简而言之,你可以往query()
内传入类名或者类的属性
继续
我们来看下传入类是怎么样的:
>>> for instance in session.query(User).order_by(User.id):
... print(instance.name, instance.fullname)
ed Ed Jones
wendy Wendy Williams
mary Mary Contrary
fred Fred Flinstone
我们再来看下传入类属性
>>> for name, fullname in session.query(User.name, User.fullname):
... print(name, fullname)
ed Ed Jones
wendy Wendy Williams
mary Mary Contrary
fred Fred Flinstone
SQLAlchemy 会根据你传入的参数个数,然后返回数量上与之匹配的tuple
,
当然了你可以使用all()
这个函数来生成named tuple
,这个named tuple
是通过SQLAlchemy提供的keyedTuple
类来完成的:
>>> for row in session.query(User, User.name).all():
... print(row.User, row.name)
<User(name='ed', fullname='Ed Jones', password='f8s7ccs')> ed
<User(name='wendy', fullname='Wendy Williams', password='foobar')> wendy
<User(name='mary', fullname='Mary Contrary', password='xxg527')> mary
<User(name='fred', fullname='Fred Flinstone', password='blah')> fred
你可以手动控制named tuple
的属性名字,通过使用label()
函数,我们来看下演示代码
>>> for row in session.query(User.name.label('name_label')).all():
... print(row.name_label)
ed
wendy
mary
fred
你可以给你的映射类取一个别名以方便区分,或者方便操作。aliased()
函数可以帮你方便的给映射类取一个名字
>>> from sqlalchemy.orm import aliased
>>> user_alias = aliased(User, name='user_alias')
SQL>>> for row in session.query(user_alias, user_alias.name).all():
... print(row.user_alias)
<User(name='ed', fullname='Ed Jones', password='f8s7ccs')>
<User(name='wendy', fullname='Wendy Williams', password='foobar')>
<User(name='mary', fullname='Mary Contrary', password='xxg527')>
<User(name='fred', fullname='Fred Flinstone', password='blah')>
关于数据库LIMIT
和 OFFSET
的操作,我可以使用SQLAlchemy提供的order_by()
filter()
filter_by()
配合Python的 slices 来进行操作
我们看一些实例
>>> for u in session.query(User).order_by(User.id)[1:3]:
... print(u)
<User(name='wendy', fullname='Wendy Williams', password='foobar')>
<User(name='mary', fullname='Mary Contrary', password='xxg527')>
filter_by()
>>> for name, in session.query(User.name).\
... filter_by(fullname='Ed Jones'):
... print(name)
ed
filter()
可以让你可以更灵活的使用 regular python operators
来表达你想的结果。
>>> for name, in session.query(User.name).\
... filter(User.fullname=='Ed Jones'):
... print(name)
ed
Query
对象是完全generative
(你可以理解为,永动机调用),意味着你可以在Query
对象后面使用N个filter()
配合regular python operators
来完成数据筛选
>>> for user in session.query(User).\
... filter(User.name=='ed').\
... filter(User.fullname=='Ed Jones'):
... print(user)
<User(name='ed', fullname='Ed Jones', password='f8s7ccs')>
Common Filter Operators
下面总结了一些常用的 filter operators,作为菜鸡,或者轻度使用数据库的使用者来说,已经可以满足日常使用的大部分需求了
equals:
query.filter(User.name == 'ed')
not equals:
query.filter(User.name != 'ed')
LIKE:
query.filter(User.name.like('%ed%'))
ILKIE(大小写敏感):
query.filter(User.name.ilike('%ed%'))
-
IN:
query.filter(User.name.in_(['ed', 'wendy', 'jack'])) # 你可以在in里面再传入一个query object(可以理解为在list内寻找): query.filter(User.name.in_( session.query(User.name).filter(User.name.like('%ed%')) ))
NOT IN:
query.filter(~User.name.in_(['ed', 'wendy', 'jack']))
-
IS NULL:
query.filter(User.name == None) # 或者 query.filter(User.name.is_(None))
-
IS NOT NULL:
query.filter(User.name != None) # 或者 query.filter(User.name.isnot(None))
-
AND:
# use and_() from sqlalchemy import and_ query.filter(and_(User.name == 'ed', User.fullname == 'Ed Jones')) # 或者 query.filter(User.name == 'ed', User.fullname == 'Ed Jones') # 或者 query.filter(User.name == 'ed').filter(User.fullname == 'Ed Jones')
-
OR:
from sqlalchemy import or_ query.filter(or_(User.name == 'ed', User.name == 'wendy'))
MATCH:`query.filter(User.name.match('wendy'))