python ORM框架:SqlAlchemy

      ORM,对象关系映射,即Object Relational Mapping的简称,通过ORM框架将编程语言中的对象模型与数据库的关系模型建立映射关系,这样做的目的:简化sql语言操作数据库的繁琐过程(原生sql的编写及拼接等),转而直接使用对象模型来操作数据库做替代

第一部分

      SqlAlchemy本身无法直接操作数据库,它是建立在第三方数据库API(如python 中的pymysql库)之上,应用程序调用对象模型进行增删改查等操作时,将对象转化成sql语句,然后再通过API调用执行已经转换好的sql语句

安装

  pip install sqlalchemy
  pip install pymysql #这里笔者使用的数据API是pymysql

应用

- 配置及创建数据库引擎

      SqlAlchemy 支持间接调用多种数据库API,根据不能的配置文件调用不同的数据库API

#常见配置文件:即database url,创建数据库引擎需要
MySQL-Python:mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>

pymysql:mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]

MySQL-Connector:mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>

cx_Oracle:oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]
- 创建数据库引擎

      * 注意 *:带上charset=utf8参数,防止中文乱码

#初始化数据库连接
from sqlalchemy import create_engine
url="mysql+pymysql://[账号]:[密码]@[主机]:[端口]/[数据库]?charset=utf8" #这里笔者使用的mysql数据库,pymysql API与数据库交互,添加的charset可防止中文乱码
engine=create_engine(url,echo=False,encoding="utf-8")  #url为配置文件,echo调试参数,值为为true打印整个sql执行过程
- 创建会话(session)

      通过sessionmaker工厂方法,我们得到一个类,默认返回Session类,也可以自定义Session类
方法:
sessionmaker( bind=None, class_=Session, autoflush=True,autocommit=False,expire_on_commit=True,info=None, **kw)

#示例1:直接调用sessionmaker
from sqlalchemy.orm import sessionmaker
SessionClass=sessionmaker(bind=engine)#利用工厂模式获取SessionClass
session_obj=SessionClass() #创建session对象,此时已绑定数据库引擎,但是未关联任何的对象模型
#示例1:使用scoped_session
from sqlalchemy.orm import scoped_session
SessionClass=scoped_session(sessionmaker(bind=engine))#利用工厂模式获取SessionClass
session_obj=SessionClass() #创建session对象,此时已绑定数据库引擎,但是未关联任何的对象模型

scoped_session VS Session
      Session:多次创建的Session对象是不同的
      scoped_session:首先通过sessionmaker工厂创建Session对象,然后对Session对象进行相应的管理(先在Registry中找之前是否创建过Session,若没有,则创建并注册,有,则直接返回),这样的目的:同一个线程维护一个session对象,保证了线程的安全性

- 与数据库交互

    常用操作:与sql语言一致,主要是增删改查,接下来就简要概述这4大类

******* 增 *******

session.add(object) #在数据库中增加一个对象实例
session.add_all([object]) #在数据库中增加多个对象实例,参数为列表形式
session.commit() #提交,否则未入口

******* 查 *******

#备注:以下均已object代表对象模型,object.prop代表对象object的prop属性
session.query(object) #查询object对应的关系表,相当于select * from tables
session.query(object).first() #查询结果取第一条,没有返回none
session.query(object).filter(object.prop) #条件查询,filter相当于where
session.query(object).order_by(object.prop) #排序,默认升序,降序用desc
session.query(object).order_by(object.prop.desc()).limit(10) #降序,及限制10条
session.query(object.prop.label("别名")).filter(object.prop.like("%同同mony")) #模糊查询及给字段取别名
#使用聚合函数,sum、count等
from sqlalchemy import func
session.query(func.sum(object.prop).label("别名")

******* 改 *******

session.query(object).filter(object.prop>20).update({"prop1": 'values'})#批量更新,若没有过滤条件,这更新表中所有记录
myuser = Session.query(object).filter(object.prop>20).first()
object.prop2= 'value2' #单条更新,可直接修改对象
session.commit()

******* 删 *******

res = session.query(object).filter(object.prop>20).delete() 
session.commit()  

第二部分

   掌握了基本概念和使用,为了更高效、更快捷将关系表转化成对象,不得不提sqlacodegen工具
a.安装
    pip install sqlacodegen
b.使用
  sqlacodegen url [opts]
    这里的url就是sqlalchemy中create_engine使用的参数,但是当账号密码含有特殊字符时,同样的url,在sqlacodegen命令中会报错,识别不出账号、密码、端口等信息,此时可通过给账号和密码加引号解决
    opts:
       --tables TABLES 指定表,默认将所有表转化成对象
       --noindexes 忽略索引
       --noviews 忽略视图
       --noclasses 不生成类,仅生成表
       --outfile OUTFILE 输出文件
示例:
sqlacodegen --noviews --noconstraints --noclasses --noindexes --outfile 对应py文件路径 url【同create engine处使用的】
注意 :当账号和密码包含特殊字符时,需要用引号,否则自动识别不出账号、密码、端口等信息

示例1:

#不使用 `--noclasses`导出的对象
from sqlalchemy import BIGINT, Column, DateTime, Float, String, text
from sqlalchemy.dialects.mysql.types import TINYINT
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
metadata = Base.metadata

class TDeviceActivate(Base):
    __tablename__ = 't_device_activate'

    id = Column(BIGINT(10), nullable=False)
    user_id = Column(BIGINT(10), nullable=False)
    device_id = Column(String(32), primary_key=True, nullable=False)
    mac = Column(String(30))
    uuid = Column(String(32))
    firmware_type = Column(String(16), primary_key=True, nullable=False)
    activate_time = Column(DateTime, nullable=False)
    create_date = Column(DateTime, nullable=False)
    ip_address = Column(String(50))
    longitude = Column(Float(10))
    latitude = Column(Float(10))
    expires_time = Column(DateTime)
    type = Column(TINYINT(10), server_default=text("'1'"))

示例2

#使用 `--noclasses`参数导出的对象
from sqlalchemy import BIGINT, Column, DateTime, Float, MetaData, String, Table, text
from sqlalchemy.dialects.mysql.types import TINYINT

metadata = MetaData()


t_t_device_activate = Table(
    't_device_activate', metadata,
    Column('id', BIGINT(10), nullable=False),
    Column('user_id', BIGINT(10), nullable=False),
    Column('device_id', String(32), primary_key=True, nullable=False),
    Column('mac', String(30)),
    Column('uuid', String(32)),
    Column('firmware_type', String(16), primary_key=True, nullable=False),
    Column('activate_time', DateTime, nullable=False),
    Column('create_date', DateTime, nullable=False),
    Column('ip_address', String(50)),
    Column('longitude', Float(10)),
    Column('latitude', Float(10)),
    Column('expires_time', DateTime),
    Column('type', TINYINT(10), server_default=text("'1'"))
)

总结

     在UI回归测试脚本中,通常涉及到与数据库打交道,开始时候主要使用pymysql API 与数据交互,但是随着使用频率的增加,直接书写sql变得繁琐,便尝试使用orm的方式

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,454评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,553评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,921评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,648评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,770评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,950评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,090评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,817评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,275评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,592评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,724评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,409评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,052评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,815评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,043评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,503评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,627评论 2 350

推荐阅读更多精彩内容