Python SQLAlchemy ORM教程(2)

由于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提供的方法,你需要通过sessionquery()方法生成一个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')>

关于数据库LIMITOFFSET 的操作,我可以使用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'))

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容