Python数据库ORM SQLAlchemy 0.7学习笔记(6) 查询

1. 返回列表和标量(Scalar)

前面我们注意到Query对象可以返回可迭代的值(iterator value),然后我们可以通过for in来查询。不过Query对象的all()one()以及first()方法将返回非迭代值(non-iterator value),比如说all()返回的是一个列表:

>>> query = session.query(User).\
>>>         filter(User.name.like('%ed')).order_by(User.id)
>>> query.all() 
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 LIKE ? ORDER BY users.id
('%ed',)
 
[User('ed','Ed Jones', 'f8s7ccs'), User('fred','Fred Flinstone', 'blah')]

继续阅读“Python数据库ORM SQLAlchemy 0.7学习笔记(6) 查询”

Python数据库ORM SQLAlchemy 0.7学习笔记(5) 查询

前期我们做了充足的准备工作,现在该是关键内容之一查询了,当然前面的文章中或多或少的穿插了些有关查询的东西,比如一个查询(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

继续阅读“Python数据库ORM SQLAlchemy 0.7学习笔记(5) 查询”

Python数据库ORM SQLAlchemy 0.7学习笔记(4) 添加对象

1. 添加一个新对象

前面介绍了映射到实体表的映射类User,如果我们想将其持久化(Persist),那么就需要将这个由User类建立的对象实例添加到我们先前创建的Session会话实例中:

ed_user = User('ed', 'Ed Jones', 'edspassword')
session.add(ed_user)

上面两段代码执行完后对象持久化了么?你或许会兴冲冲的跑去数据库里查看,结果却失望而归——数据库里什么都没有。为什么呢?因为SQLAlchemy采取的是Lazyload策略,也就是说现在这个对象被标记为Pending准备状态,但没有执行任何可能导致数据库变化的SQL语句。那么什么时候会执行SQL语句并真正持久化呢?这个要等SQLAlchemy觉得需要的时候,比如我们现在查询这个对象、对象的一个属性或者显式的调用flush方法,这时候SQLAlchemy觉得它“是时候”或者“不得不”执行SQL数据库查询以便于把标记为Pending的数据写入数据库表中了。假如这时候你执行的获取对象、对象属性或者类似的操作,SQLAlchemy在执行完SQL语句后会将你所要查询的数据反馈给你。

继续阅读“Python数据库ORM SQLAlchemy 0.7学习笔记(4) 添加对象”

Python数据库ORM SQLAlchemy 0.7学习笔记(3) 会话

1. 创建映射类的实例(Instance)

前面介绍了如何将数据库实体表映射到Python类上,下面我们可以创建这个类的一个实例(Instance),我们还是以前一篇文章的User类为例,让我们创建User对象:

>>> ed_user = User('ed', 'Ed Jones', 'edspassword')
>>> ed_user.name
'ed'
>>> ed_user.password
'edspassword'
>>> str(ed_user.id)
'None'

和普通的Python类一样实例化,大家可能会问为什么ed_user.id会是None值,首先id这个属性没有通过__init__()构造方法初始化,所以默认会因为先前定义的ORM的id列(Column)而产生一个None值,在默认情况下,ORM会为所有被映射的表列创建类属性,这些属性是通过Python语言中描述符(Descriptors)机制来实现的。所以这些属性的使用会包含一些额外的行为,包括跟踪修改,或者当需要时自动从数据库加载新的数据,也就是说我们在使用这些属性时,包括修改或者读取,都会触发ORM内部的一系列动作。

继续阅读“Python数据库ORM SQLAlchemy 0.7学习笔记(3) 会话”

Python数据库ORM SQLAlchemy 0.7学习笔记(2) 定义映射

昨天简单介绍了SQLAlchemy的使用,但是没有能够涉及其最精彩的ORM部分,今天我将简单说明一下,当然主要还是讲解官方文档的内容,由于是学习笔记,有可能存在精简或者自己理解的部分,不做权威依据。

当我们开始使用ORM,一种可配置的结构可以用于描述我们的数据库表,稍后我们定义的类将会被映射到这些表上。当然现代的SQLAlchemy(新版本SQLAlchemy,原文是modern SQLAlchemy)使用Declarative把这两件事一起做了,即允许我们把创建类和描述定义数据库表以及它们之间的映射关系一次搞定。

这段话是什么意思呢?简单来说吧,SQLAlchemy分为Classic (经典模式)和Modern (现代模式),Classic定义数据库表的模式比较传统,需要先描述这个表。

1. Classic 映射

比如以官方文档中的例子,我们拥有表结构如下:

CREATE TABLE [users] (
  [id]       INTEGER PRIMARY KEY,
  [name]     TEXT NOT NULL,
  [fullname] TEXT NOT NULL,
  [password] TEXT NOT NULL
);

继续阅读“Python数据库ORM SQLAlchemy 0.7学习笔记(2) 定义映射”

Python数据库ORM SQLAlchemy 0.7学习笔记(1) 概要

最近正好在寻求一种Python的数据库ORM (Object Relational Mapper),SQLAlchemy (项目主页)这个开源项目进入了我的视线,本来想尝试着使用Django的ORM模块的,无奈Django的模块联系比较紧密,没能单独分拆下来,一定程度上说明Django自成体系的生态系统在给我们带来快速便捷的开发环境的同时牺牲了组装的灵活性。

初次学习,也没实质感觉到SQLAlchemy的好处,不过看其介绍的很多大公司均采用该项目,而且其支持的数据库还是蛮丰富的,所以我觉得花点时间研究还是值得的。不过令人遗憾的是关于SQLAlchemy的中文资料比较少,所以对于我们这种英语不佳的带来了一定的麻烦。

研究一个项目最好的办法就是阅读其官方提供的说明文档,当然很轻松就找到了SQLAlchemy的文档 (0.7)。文档的格式和大多数项目一样,有下载安装说明,有示例,有快速上手教程。不过我还是习惯下载个PDF慢慢研究

下面就将我近期的阅读学习做个笔记,当然这个仅供参考,里面可能有自己的一些猜测和想法,不作权威依据,不当之处还希望指出。

继续阅读“Python数据库ORM SQLAlchemy 0.7学习笔记(1) 概要”

Python 三元条件判断表达式(and or/if else)

之前学习的Python提到了对于类似C语言的三元条件表达式condition ? true_part : false_part,虽然Python没有三目运算符(?:),但也有类似的替代方案,那就是true_part if condition else false_part

>>> 1 if True else 0
1
>>> 1 if False else 0
0
>>> "Fire" if True else "Water"
'Fire'
>>> "Fire" if False else "Water"
'Water'

在编程中我也一直这么用了,直到有一天发现了一个有趣的技巧,那就是and-or技巧,利用条件判断的优先特性来实现三元条件判断,比如P∧Q,在Python中如果P为假,那么Python将不会继续执行Q,而直接判定整个表达式为假(P值),当然如果P为真,那就还要继续执行Q来决定整个表达式值;同样的P∨Q,如果P为真,那么就不会继续执行Q了…

继续阅读“Python 三元条件判断表达式(and or/if else)”

IIS7以CGI方式运行Python脚本

由于接触到Python Web开发,正好把最简单的CGI方式研究了一下,话说在Windows下配置Python的Web开发还真的蛮麻烦的,Linux下配置倒挺容易,正好微软有技术文章《Using Python Scripts with IIS》介绍了这些内容,此文介绍了两种方法,一是使用ASP引擎来运行Python脚本,这个可能需要用到ActivePython,当然ASP技术已经过时了,我今天就简单介绍下CGI模块运行方式。

编写简单的支持CGI的Python脚本(本文介绍3.2版本的Python):

print("Status: 200 OK")
print("Content-type: text/html")
print() # 打印一行空白行,用于分隔HTTP Header和正文
 
print("<h1>Hello World!</h1>")

这样就可以了,大家可以猜出CGI是将标准输出流重新定向到HTTP输出流来实现网页或者数据传输的。

当然这个在IIS中是不能直接运行的,我们需要配置一下,打开Internet 信息服务(IIS)管理器界面,选择“处理程序映射”。

继续阅读“IIS7以CGI方式运行Python脚本”

Python操作SQLite3数据库辅助类(查询构造器)

接触Python时间也不是很长的,最近有个项目需要分析数据,于是选用Python为编程语言,除了语言特性外主要还是看重Python对于SQLite3数据库良好的支持能力了,因为需要灵活处理大量的中间数据。

刚开始一些模块我还乐此不疲的写SQL语句,后来渐渐厌倦了,回想到以前捣鼓C#的时候利用反射初步构建了个SQL查询构造器,直到发现linq,于是放弃了这个计划,当然微软后来又推出了Entity Framework,这些都是后话了,而且现在我对微软的东西兴趣不是很大的,好了,扯多了,下面继续正文。

对了,再扯一句,优秀的博客程序Drupal也使用了类似的查询构造器进行数据库查询,避免直接写SQL语句,另外这样做的一点点好处就是,可以一定程度的屏蔽平台相关性,对于数据库迁移还是有帮助的。

不过我今天介绍的数据库辅助类查询构造器是个很简单的东东,甚至只限于SQLite数据库,如果有童鞋感兴趣可以完善下,我目前只要操作SQLite顺手就可以了,对于比较大的数据库应用就直接上ORM吧。

继续阅读“Python操作SQLite3数据库辅助类(查询构造器)”

Python非标准的日期字符串处理(解析、转换、比较)

我之前有篇文章介绍利用VB/VBScript根据出生日期来计算年龄,文中介绍了函数ComputeAge,当时为了处理一些Word或者Excel中非标准的时间的,当然这个函数除了能计算年龄外也能转换这些非标准的时间字符串到程序语言支持的时间变量。

只要不是太畸形的时间字符串表示法,基本上ComputeAge都能处理,不过这次有个项目需要用到Python,于是要写个类似的函数来分析处理非标准的时间表示字符串。

当然我不想像上次那样写上一堆if,然后再用程序语言专有函数来分割处理字符串,再转换,太吃力不讨好了,所以我这次尝试使用正则表达式进行模式匹配切割字符串。

我分析了形如19920203、199203、1992.02.03、1992.02、1992-02-03、1992-02、920203时间格式特征,列出了正则表达式如下:

^((?:19|20)?\d{2})[-.]?((?:[0-1]?|1)[0-9])[-.]?((?:[0-3]?|[1-3])[0-9])?$

当然这个表达式还不是很完善,只能做简单的切割,不能判断日期的合法性,关于日期是否合法,我还是交给Python的时间功能来处理吧。

继续阅读“Python非标准的日期字符串处理(解析、转换、比较)”