Python ORM框架SQLAlchemy学习笔记之数据查询实例


Posted in Python onJune 10, 2014

前期我们做了充足的准备工作,现在该是关键内容之一查询了,当然前面的文章中或多或少的穿插了些有关查询的东西,比如一个查询(Query)对象就是通过Session会话的query()方法获取的,需要注意的是这个方法的参数数目是可变的,也就是说我们可以传入任意多的参数数目,参数的类型可以是任意的类组合或者是类的名称,接下来我们的例子就说明了这一点,我们让Query对象加载了User实例。

>>> for instance in session.query(User).order_by(User.id): 
...     print instance.name, instance.fullname
SELECT users.id AS users_id,
        users.name AS users_name,
        users.fullname AS users_fullname,
        users.password AS users_password
FROM users ORDER BY users.id
()ed Ed Jones
wendy Wendy Williams
mary Mary Contrary
fred Fred Flinstone

当然通过这个例子我们得到Query对象返回的是一组可迭代的User实例表,然后我们通过for in语句访问,比如说这里可以依次输出“用户名”instance.name和“用户全名”instance.fullname。大家可能还注意到后面有个.order_by(User.id),这个和SQL语句一样的,指示结果集按User.id所映射的表列进行排序。

假设我们仅仅只需要“用户名”和“用户全名”,对于对象实例的其他属性不感兴趣的话,也可以直接查询它们(类的属性名称),当然这里的前提是这个类必须是ORM映射的,无论何时,任意数目的类实体或者基于列的实体均可以作为query()方法的参数,当然最终Query对象会返回元组类型。

>>> for name, fullname in session.query(User.name, User.fullname): 
...     print name, fullname
SELECT users.name AS users_name,
        users.fullname AS users_fullname
FROM users
()ed Ed Jones
wendy Wendy Williams
mary Mary Contrary
fred Fred Flinstone

返回的元组类型也可以被看作是普通的Python对象,属性名称归属性名称,类型名称归类型名称,比如下面的例子:
>>> for row in session.query(User, User.name).all(): 
...    print row.User, row.name
SELECT users.id AS users_id,
        users.name AS users_name,
        users.fullname AS users_fullname,
        users.password AS users_password
FROM users
()<User('ed','Ed Jones', 'f8s7ccs')> ed
<User('wendy','Wendy Williams', 'foobar')> wendy
<User('mary','Mary Contrary', 'xxg527')> mary
<User('fred','Fred Flinstone', 'blah')> fred

当然你也可以搞点个性化,比如通过label()方法改变单独的列表达式名称,当然这个方法只有在映射到实体表的列元素对象(ColumnElement-derived)中存在(比如 User.name):
>>> for row in session.query(User.name.label('name_label')).all(): 
...    print(row.name_label)
SELECT users.name AS name_label
FROM users
()ed
wendy
mary
fred

之前我们看到查询对象实例必须用到实体类的全名(User),假设我们要多次使用这个实体类名作为查询对象(比如表连接操作)query()的参数,则我们可以给它取个“别名”,然后就可以通过别名来传入参数:
>>> from sqlalchemy.orm import aliased
>>> user_alias = aliased(User, name='user_alias')>>> for row in session.query(user_alias, user_alias.name).all(): 
...    print row.user_alias
SELECT user_alias.id AS user_alias_id,
        user_alias.name AS user_alias_name,
        user_alias.fullname AS user_alias_fullname,
        user_alias.password AS user_alias_password
FROM users AS user_alias
()
<User('ed','Ed Jones', 'f8s7ccs')>
<User('wendy','Wendy Williams', 'foobar')>
<User('mary','Mary Contrary', 'xxg527')>
<User('fred','Fred Flinstone', 'blah')>

学过MySQL等这类数据库的同学可能知道LIMIT和OFFSET这两个SQL操作,这个能够很方便的帮助我们控制记录的数目和位置,常常被用于数据分页操作,当然这类操作SQLAlchemy的Query对象已经帮我们想好了,而且很简单的可以通过Python数组分片来实现,这个操作常常和ORDER BY一起使用:
>>> for u in session.query(User).order_by(User.id)[1:3]: 
...    print u
SELECT users.id AS users_id,
        users.name AS users_name,
        users.fullname AS users_fullname,
        users.password AS users_password
FROM users ORDER BY users.id
LIMIT ? OFFSET ?
(2, 1)<User('wendy','Wendy Williams', 'foobar')>
<User('mary','Mary Contrary', 'xxg527')>

假如我们需要筛选过滤特定结果,则可以使用filter_by()方法,这个方法使用关键词参数:
>>> for name, in session.query(User.name).\
...             filter_by(fullname='Ed Jones'): 
...    print name
SELECT users.name AS users_name FROM users
WHERE users.fullname = ?
('Ed Jones',)ed

或者使用filter()同样能达到目的,不过需要注意的是其使用了更加灵活的类似SQL语句的表达式结构,这意味着你可以在其内部使用Python自身的操作符,比如比较操作:
>>> for name, in session.query(User.name).\
...             filter(User.fullname=='Ed Jones'): 
...    print name
SELECT users.name AS users_name FROM users
WHERE users.fullname = ?
('Ed Jones',)ed

注意这里的User.fullname=='Ed Jones',比较操作与Ed Jones相等的才筛选。

当然强大的Query对象有个很有用的特性,那就是它是可以串联的,意味着Query对象的每一步操作将会返回一个Query对象,你可以将相同的方法串联到一起形成表达式结构,假如说我们要查询用户名为”ed”并且全名为”Ed Jones”的用户,你可以直接串联调用filter()两次,表示SQL语句里的AND连接:

>>> for user in session.query(User).\
...          filter(User.name=='ed').\
...          filter(User.fullname=='Ed Jones'): 
...    print user
SELECT users.id AS users_id,
        users.name AS users_name,
        users.fullname AS users_fullname,
        users.password AS users_password
FROM users
WHERE users.name = ? AND users.fullname = ?
('ed', 'Ed Jones')<User('ed','Ed Jones', 'f8s7ccs')>

下面列举一些使用filter()常见的筛选过滤操作:

1. 相等

query.filter(User.name == 'ed')

2. 不等
query.filter(User.name != 'ed')

3. LIKE
query.filter(User.name.like('%ed%'))

4. IN
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%'))))

5. NOT IN
query.filter(~User.name.in_(['ed', 'wendy', 'jack']))

6. IS NULL
filter(User.name == None)

7. IS NOT NULL
filter(User.name != None)

8. AND
from sqlalchemy import and_
filter(and_(User.name == 'ed', User.fullname == 'Ed Jones'))# or call filter()/filter_by() multiple times
filter(User.name == 'ed').filter(User.fullname == 'Ed Jones')

9. OR
from sqlalchemy import or_
filter(or_(User.name == 'ed', User.name == 'wendy'))

10. 匹配
query.filter(User.name.match('wendy'))

match()参数内容由数据库后台指定。(注:原文是“The contents of the match parameter are database backend specific.”,不太明白这个操作的意思)

好了,今天就介绍这么多,基本上都是蹩脚的翻译,希望对大家能够帮助

Python 相关文章推荐
解决Python出现_warn_unsafe_extraction问题的方法
Mar 24 Python
200行自定义python异步非阻塞Web框架
Mar 15 Python
python 如何快速找出两个电子表中数据的差异
May 26 Python
python Pygame的具体使用讲解
Nov 03 Python
Python学习pygal绘制线图代码分享
Dec 09 Python
python实现读取大文件并逐行写入另外一个文件
Apr 19 Python
selenium+python设置爬虫代理IP的方法
Nov 29 Python
Python面向对象程序设计构造函数和析构函数用法分析
Apr 12 Python
新手如何发布Python项目开源包过程详解
Jul 11 Python
学习Python列表的基础知识汇总
Mar 10 Python
Pycharm连接gitlab实现过程图解
Sep 01 Python
Python可变与不可变数据和深拷贝与浅拷贝
Apr 06 Python
Python ORM框架SQLAlchemy学习笔记之数据添加和事务回滚介绍
Jun 10 #Python
Python ORM框架SQLAlchemy学习笔记之映射类使用实例和Session会话介绍
Jun 10 #Python
Python ORM框架SQLAlchemy学习笔记之关系映射实例
Jun 10 #Python
Python ORM框架SQLAlchemy学习笔记之安装和简单查询实例
Jun 10 #Python
Python使用htpasswd实现基本认证授权的例子
Jun 10 #Python
python网络编程学习笔记(10):webpy框架
Jun 09 #Python
python网络编程学习笔记(九):数据库客户端 DB-API
Jun 09 #Python
You might like
用PHP写的MySQL数据库用户认证系统代码
2007/03/22 PHP
Yii 访问 Gii(脚手架)时出现 403 错误
2018/06/06 PHP
jquery 分页控件实现代码
2009/11/30 Javascript
JavaScript DOM 学习第九章 选取范围的介绍
2010/02/19 Javascript
js中replace的用法总结
2013/12/27 Javascript
一个html5播放视频的video控件只支持android的默认格式mp4和3gp
2014/05/08 Javascript
JS实现点击按钮自动增加一个单元格的方法
2015/03/09 Javascript
js+html5获取用户地理位置信息并在Google地图上显示的方法
2015/06/05 Javascript
JQuery.Ajax()的data参数类型实例详解
2015/11/20 Javascript
javascript制作照片墙及制作过程中出现的问题
2016/04/04 Javascript
原生javascript实现图片放大镜效果
2017/01/18 Javascript
bootstrap中模态框、模态框的属性实例详解
2017/02/17 Javascript
Vue中fragment.js使用方法详解
2017/03/09 Javascript
AngularJS双向绑定和依赖反转实例详解
2017/04/15 Javascript
原生js中ajax访问的实例详解
2017/09/19 Javascript
jQuery实现菜单的显示和隐藏功能示例
2018/07/24 jQuery
React注册倒计时功能的实现
2018/09/06 Javascript
理顺8个版本vue的区别(小结)
2018/09/17 Javascript
微信小程序出现wx.getLocation再次授权问题的解决方法分析
2019/01/16 Javascript
小程序input数据双向绑定实现方法
2019/10/17 Javascript
[41:41]TFT vs Secret Supermajor小组赛C组 BO3 第一场 6.3
2018/06/04 DOTA
Python实现抓取页面上链接的简单爬虫分享
2015/01/21 Python
TF-IDF与余弦相似性的应用(一) 自动提取关键词
2017/12/21 Python
Python搭建FTP服务器的方法示例
2018/01/19 Python
python操作excel的方法
2018/08/16 Python
Python Numpy库常见用法入门教程
2020/01/16 Python
利用CSS3参考手册和CSS3代码生成工具加速来学习网页制
2012/07/11 HTML / CSS
提供世界各地便宜的机票:Sky-tours
2016/07/21 全球购物
驴妈妈旅游网:中国新型的B2C旅游电子商务网站
2016/08/16 全球购物
Lacoste(法国鳄鱼)加拿大官网:以标志性的POLO衫而闻名
2019/05/15 全球购物
"火柴棍式"程序员面试题
2014/03/16 面试题
Linux操作面试题
2012/05/16 面试题
小学班主任评语大全
2014/04/23 职场文书
论群众路线学习心得体会
2014/10/31 职场文书
2019年最新证婚词精选集!
2019/06/28 职场文书
源码分析Redis中 set 和 sorted set 的使用方法
2022/03/22 Redis