由于SQLAlchemy 中文資料比較少裳凸,所以根據(jù)官網(wǎng)給的tutorial外加其他大佬寫的中文資料整合以后準備寫一個SQLAlchemy 系列的基礎入門教程侍瑟。本系列可能會夾雜一些個人對于python 戈毒、SQLAlchemy 以及ORM的理解,如有出錯部分麸拄,請指正我星著。
版本信息:
- SQLAlchemy 1.2.15
- Python 3.6+
- Mac OS 10.14
- DB基于SQLite
前序文章Python SQLAlchemy ORM教程(1)講了怎么建立你數(shù)據(jù)庫,插入數(shù)據(jù)则剃,也講了engine和session的相關概念耘柱,接下來我們開始看看怎么花式取數(shù)據(jù)
Querying
SQLAlchemy的官方教程說,你的任何查詢都是基于session
的棍现,是session
提供的方法调煎,你需要通過session
的query()
方法生成一個query
對象。query()
是必須傳入一個參數(shù)的己肮,這是參數(shù)可以是一個combination of class
或者 calss-instrumented descriptors
instrumented
關于 combination of class
可以簡單理解為類士袄,可能class-instructmented descriptors
比較容易讓人發(fā)懵,
instrumentations
是將屬性附加到類的一個過程谎僻,也可以叫Python Descriptors
我們來看一些例子:
#__get__
myobject.someattribut
#__set__
myobject.someattribut = "foo"
#__del__
del myobject.someattribut
以上的行為都可以稱為 instrumentation
簡而言之娄柳,你可以往query()
內(nèi)傳入類名或者類的屬性
繼續(xù)
我們來看下傳入類是怎么樣的:
>>> 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 會根據(jù)你傳入的參數(shù)個數(shù),然后返回數(shù)量上與之匹配的tuple
艘绍,
當然了你可以使用all()
這個函數(shù)來生成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()
函數(shù)诱鞠,我們來看下演示代碼
>>> for row in session.query(User.name.label('name_label')).all():
... print(row.name_label)
ed
wendy
mary
fred
你可以給你的映射類取一個別名以方便區(qū)分挎挖,或者方便操作。aliased()
函數(shù)可以幫你方便的給映射類取一個名字
>>> 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')>
關于數(shù)據(jù)庫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
來表達你想的結(jié)果蕉朵。
>>> for name, in session.query(User.name).\
... filter(User.fullname=='Ed Jones'):
... print(name)
ed
Query
對象是完全generative
(你可以理解為,永動機調(diào)用)阳掐,意味著你可以在Query
對象后面使用N個filter()
配合regular python operators
來完成數(shù)據(jù)篩選
>>> 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
下面總結(jié)了一些常用的 filter operators墓造,作為菜雞,或者輕度使用數(shù)據(jù)庫的使用者來說锚烦,已經(jīng)可以滿足日常使用的大部分需求了
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內(nèi)尋找): 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'))