【SQLAlchemy】python最常用ORM (二)

http://www.kardel.xyz/blog/sqlalchemypython%E6%9C%80%E5%B8%B8%E7%94%A8orm-%E4%BA%8C/

上文介绍了创建engine,创建映射关系,create/drop表,本文,我们来聊下最常用的DML的实现

在此之前,我们说过,我们一般并不会直接使用Engine,如engine.execute()去执行sql,更多的,我们通过session实现

ORM对数据库的入口即是Session,当我们构建应用时,和create_engine的同一级别下,我们定义一个Session类来作为生成新的Session的Factory类

Session的创建

先看代码:

#! /usr/bin/env python

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

connect_args = {'check_same_thread': False}
engine = create_engine(engine, echo=False, connect_args=connect_args)

session = sessionmaker(bind=engine)()

分析以上代码
前半部分我们之前已经说过的engine的创建
最后一行,sessionmaker(bind=engine)返回一个Session的Factory类,即也可以写成这样:

Session = sessionmaker(bind=engine)
session = Session()

这样,我们得到一个session对象,现在,我们可以实现对表的操作了

add

我们要在users表中插入一条数据,类比的,相当于,我们需要将User对象存入数据库,session提供add方法

user = User(name='ed', password='edspassword')
session.add(user)

执行完以上操作,我们将user存入session,但并未提交,也就是说,数据并未落盘存入数据库。
Session将会在需要的时候执行相应的SQL命令,这个过程我们称之为flush。如果我们试图查询Ed Jones,所有处于pending状态的信息将会首先被flush,然后负责进行查询的SQL语言在此之后立即被执行。

例如,我们创建一个查询来获取刚刚我们创建的用户(涉及查询的部分我们后续会详细介绍)。这个查询会返回一个和我们之前添加的用户相同的用户实例。事实上这里的Session判断出来了需要返回的行和已经存在内存中的一个映射实例应当是同一个,所以我们会得到一个和之前完全相同的实例

这里ORM所表现的理念,我们称之为identity map。这个设计理念保证了在一个Session对于一个制定行的操作,作用于同一个内存实例上。当一个拥有特定主键的对象出现在Session中时,所有的查询操作对这个主键都会返回一个相同的Python对象。并且,如果你试图引入重复了主键的新的对象时,系统会产生一个错误来阻止你的操作。

如果我们希望改变Ed的密码,可以直接修改之:

user.password = 'xxxxxx'

最后,我们使用commit将以上的处理flush到数据库

session.commit()

另外,我们也可以使用add_all()来批量插入

session.add_all([
		User(name='a',  password='foobar'),
		User(name='b', password='xxg527'),
		User(name='c',  password='blah')])

query

Session的query函数会返回一个Query对象。query函数可以接受多种参数类型。可以是类,或者是类的instrumented descriptor。然后我们可以通过filter函数在query进行筛选。

下面的这些操作符可以应用在filter函数中

equals:

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

not equals:

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

LIKE:

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

IN:

query.filter(User.name.in_(['ed', 'jack']))

# works with query objects too:
query.filter(User.name.in_(
		session.query(User.name).filter(User.name.like('%ed%'))
))

NOT IN:

query.filter(~User.name.in_(['ed', 'jack']))

IS NULL:

query.filter(User.name == None)

# alternatively, if pep8/linters are a concern
query.filter(User.name.is_(None))

IS NOT NULL:

query.filter(User.name != None)

# alternatively, if pep8/linters are a concern
query.filter(User.name.isnot(None))

AND:

# or send multiple expressions to .filter()
query.filter(User.name == 'ed', User.passwd == 'aaas')

OR:

from sqlalchemy import or_
query.filter(or_(User.name == 'ed', User.password == 'asdf'))

MATCH:

query.filter(User.name.match('wendy'))

同时,我们也可以在filter中使用嵌入式的sql
比如:

from sqlalchemy import text
for user in session.query(User).\
			filter(text("id<224")).\
			order_by(text("id")).all():

最后,query返回的是generative的对象,我们还可以通过一些函数还得到我们需要的直观结果:

all(): 返回列表

first(): 返回第一个元素

one(): 只返回一个元素,当有多个结果,异常

limit(): 返回计数,等于select count(*)

delete & update

有了query对象,我们可以基于此,进行删除或更新操作

query.delete()
query.update(update_dict, synchronize_session='fetch')

参考:

https://www.jianshu.com/p/0d234e14b5d3

https://www.jianshu.com/p/8d085e2f2657

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值