Tornado SQLAlchemy 操作
2017-12-28 本文已影响35人
依旧丶森
Tornado 曾经支持简单的 ORM 操作!就是可以通过自定义 sql 语句的方式,来完成数据对象的的增删改查操作[并不是面向对象的],后来把 ORM 操作作为了一个独立的模块进行处理,不再有内置的ORM支持!
Tornado 在实际使用时需要和第三方模块结合起来完成数据模型对象的ORM操作。
比较常用的操作手段:使用 pymysql / torndb / sqlalchemy ,这里主要用sqlalchemy。
参考官方文档(http://docs.sqlalchemy.org/en/latest/orm/tutorial.html)
1. 安装模块
pip install sqlalchemy
#安装完成即可通过导入模块,查看版本号看是否安装成功
>>> import sqlalchemy
>>> print(sqlalchemy.__version__)
1.2.0b3
2. 建立连接
ORM操作的核心,就是将程序中的对象要在数据库中进行增删改查操作
from sqlalchemy import create_engine # 创建引擎对象的模块
from sqlalchemy.orm import sessionmaker # 创建和数据库连接会话
from sqlalchemy import Column,String,Integer #内置的创建类的方法属性
from sqlalchemy.ext.declarative import declarative_base #基础类模块
# sqlalchemy默认底层使用 mysqldb 完成和数据库的连接
#但是 mysqldb 不支持最新版本的 python 和 mysql 数据库的连接,一般用Pymysql进行替代。
import pymysql
pymysql.install_as_MySQLdb()
#创建数据库引擎,数据库的类名、账号、密码、登录方式、连接的数据库、数据库编码、是否显示回写
engine =create_engine('mysql://root:root@localhost/torando_db1',
encoding='utf-8',echo=True)
#创建会话对象
Session=sessionmaker(bind=engine)
sess=Session()
# 2.如果创建会话的时候还没有创建引擎对象
#Session = sessionmaker()# 创建一个会话类型
#Session.configur(bind=engine)# 将一个连接引擎注册给这个会话
#session = Session() # 得到具体的包含连接引擎的会话
#创建基础类
Base=declarative_base(bind=engine)
#自定义类型
class Person(Base):
#指定关联数据表
__tablename__ ='person'
#定义属性
id=Column(Integer,primary_key=True)
name=Column(String(30))
age=Column(Integer)
#注意:自定义的类型必须制定关联的数据库表和表中的主键,否则报错。
3.表的创建及数据状态分析(增删改)
-
Base.metadata.create_all()
将所有salalchemy管理的对象同步到数据库中产生对应的数据表 -
临时状态(游离状态):程序中直接创建的对象,临时对象
特点:程序中有数据,缓存中无数据,数据库中无数据p = Person(name="jerry", age=12) #保存并运行在内存中的~一旦程序结束,内存中的数据会清空,此时 p 对象 无 id .
-
缓存状态(托管状态):只是存在于连接会话缓存中,数据库中并没有相关数据,缓存对象。
特点:程序中有数据,缓存中有数据,数据库中无数据session.add(p) #此时还是没有 id #程序中的对象,可以通过连接会话session的add()函数,将对象交给 sqlalchemy 进行管理
-
持久状态(持久persistent状态):对象在程序中存在,在数据库中有对应的记录
特点:程序中有数据{id}, 缓存中有数据, 数据库中有数据session.commit() # 缓存中的数据,可以通过连接会话session的commit()函数,将缓存数据提交给数据库进行持久化保存
-
修改操作
特点:一旦对缓存状态的对象进行修改,此时缓存对象和数据库中的数据不一致~~就会形成脏数据,脏数据并不是不可取的,更新操作就是将这样的数据从缓存同步到数据库(commit)p.name = "shuke" # 可以通过session.dirty来查询缓存中的脏数据 session.commit()
-
删除操作
session.delete(p) # 直接删除一个缓存的数据[脏数据],通过commit()提交到数据库 session.commit() # 注意删除的只能是持久对象 #p2 = Person(id=1) #session.delete(p2) # 抛出异常~不能删除,因为p2不是持久对象is not persisted
4. 查询操作
-
- 全表查询
#1.1. 直接调用query,就相当于默认调用了all()进行了全表查询 person_list = sess.query(Person) # 1.2. 直接通过all()函数指定进行全表查询 person_list = sess.query(Person).all()
-
- 排序查询
# 通过order_by()函数可以直接指定排序方式 # 2.1. 通过 类型.属性 指定按照什么属性进行默认顺序排序 person_list = sess.query(Person).order_by(Person.id) # 2.2. 通过 -类型.属性 指定按照什么属性进行倒序排序 person_list = sess.query(Person).order_by(-Person.id) # 2.3. 通过 类型.属性,类型.属性~指定多列,表示按照多列进行排序, #~如果第一列数据相同,按照第二列进行排序,以此类推。 person_list = sess.query(Person).order_by(Person.name, Person.age)
-
- 指定列查询
# 模拟sql语句中的指定列查询 select p.name from person p; # 生成的sql语句:SELECT persons.name AS persons_name FROM persons #只查找person 的name person_list = sess.query(Person.name)
-
- 特殊操作
#如果类型的字段名称过长,不好书写的情况下,可以指定别名 #字段属性的别名,在使用过程中可以进行简化处理,也是常见的操作手段 #[属性名称一般是开发人员自定义的,有可能非常长还没有太大必要,此时操作时就需要简化] person_list = sess.query(Person.name.label("n")) for p in person_list: print(p.n) # 此时 p.n == p.name
#如果类型过长,不好书写的情况下,可以给类型指定一个别名 #类型名称的别名,慎重使用~ #类型的名称一般都已经是比较简化的名称并且能直接表述其正式意义的名称,慎重简化! #先导入模块 from sqlalchemy.orm import aliased p = aliased(Person, name="p") ...... person_list = sess.query(p).all() #此时的 p 相当于 Person
-
- 切片查询
#一般使用在数据分页查询等这样的业务中,切片查询 # 由于sqlalchemy查询的结果就是一个like list的存在,所以直接用Python的切片即可。 # 如果网页页面中的数据~需要分页展示,每页两条记录 #~start = (pageno-1)*pagecount, end: start+pagecount person_list = sess.query(Person).all()[:2] # 第一页数据 [0, 2] person_list = sess.query(Person).all()[2:4] # 第二页数据 [2, 4]
-
- filter()[常用]条件查询
- 6.1. 等值查询 | 非等值查询
person_list = sess.query(Person).filter(Person.name!="tom") person_list = sess.query(Person).filter(Person.name=="tom")
- 6.2. 模糊查询
#name 里包含 e 字母的用户 person_list = sess.query(Person).filter(Person.name.like('%e%'))
- 6.3. 范围查询:in 和 not in
# in 查询名字叫Tom 和Jerry 的所有人 person_list = sess.query(Person).filter(Person.name.in_(['tom', 'jerry'])) # not in 查询名字不叫Tom 和Jerry 的所有人 person_list = sess.query(Person).filter(~Person.name.in_(['tom', 'jerry']))
- 6.4. 空值查询 is null / is not null
# 空值 person_list = sess.query(Person).filter(Person.name == None) # 常用~但是不是规范 person_list= sess.query(Person).filter(Person.name.is_(None)) # 不太常用~pep8编码规范推荐 # 非空值 person_list = sess.query(Person).filter(Person.name != None) person_list = sess.query(Person).filter(Person.name.isnot(None))
- 6.5. 并且条件 和 或者条件 查询
# 并且条件的查询,有三种实现模式 # 第一种:多个filter person_list = sess.query(Person).filter(Person.name=="tom").filter(Person.age==12) # 第二种:一个filter,多个条件 person_list = sess.query(Person).filter(Person.name=="tom", Person.age==12) # 第三种:规范并且条件查询方式:通过and_()函数收集条件 from sqlalchemy import and_ person_list = sess.query(Person).filter(and_(Person.name=='tom', Person.age==12))
# 或者查询:or 查询,通过or_()函数进行查询 from sqlalchemy import or_ person_list = sess.query(Person).filter(or_(Person.name=='tom', Person.name=='jerry'))
- 6.6. 定制化SQL语句查询
# 导入模块 from sqlalchemy import text person_list = sess.query(Person)\ .from_statement(text("select p.id, p.name, p.age from persons p where name=:myname"))\ .params(myname="tom").all()