SQLAlchemy 快速入门、基础知识
SQLAlchemy 是Python 编程语言下的一款开源软件。提供了SQL工具包及对象关系映射(ORM)工具。
ORM, 全称Object Relational Mapping, 中文叫做对象关系映射,通过ORM,我们可以像操作类一样使用数据库的数据
ORM把表映射成类,把行作为实例,把字段作为属性,ORM在执行对象操作的时候会把对相应的操作转换为数据库原生
语句的方式来完成数据库开发工作
SQLAlchemy 至少需要3部分代码,
- 定义表
- 定义数据库连接
- 进行增、删、改、查等逻辑操作
'Hello World'入门
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
from sqlalchemy import Column, Integer, String
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
fullname = Column(String)
password = Column(String)
def __repr__(self):
return "<User(name='%s', fullname='%s', password='%s')>" % (
self.name, self.fullname, self.password)
注意
以上的例子来自SQLAlchemy 官网,数据库用的是SQLite,没有长度限制的字符串是有效的数据类型,但在MySql中则
不然,此时可以使用String的带参数形式,如String(10)来实现指定长度。
关键点解释
- 首先导入sqlalchemy.ext.declarative,declarative_base,并定义它的实例。所有表必须继承自Base。之所以这样,可以看原版英文
When using the ORM, the configurational process starts by describing the database tables we’ll be dealing with, and then by defining our own classes which will be mapped to those tables. In modern SQLAlchemy, these two tasks are usually performed together, using a system known as Declarative, which allows us to create classes that include directives to describe the actual database table they will be mapped to.
之后利用Base 定义了一个User类
- 使用tablename属性定义了表在数据库中实际的名称users
- 引入sqlalchemy包中的Column、Intege、String类型,定义User表的数据列。
定义数据库连接
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
db_connect_string='sqlite://'
engine = create_engine(db_connect_string)
SessionType = scoped_session(sessionmaker(bind=engine,expire_on_commit=False))
def GetSession():
return SessionType()
from contextlib import contextmanager
@contextmanager
def session_scope():
session = GetSession()
try:
yield session
session.commit()
except:
session.rollback()
raise
finally:
session.close()
代码解析
引入数据库和会话引擎:sqlalchemy.create_engine,sqlalchemy.orm.scoped_session,sqlalchemy.orm.sessionmaker,其中,create_engine传入了
一个数据库的URI,sqlite://表示使用了一个SQLite的内存型数据库。URI的格式如下:
dialect+driver://username:password@host:port/database。dialect是数据库的实现,比如MySql,PostgreSQL,SQLite。driver是Python对应的驱动,
如果不指定,会选择默认的驱动。比如MySQL的默认驱动是MySQldb: engine=create_engine('mysql+mysqldb://scott:tiger@localhost/foo'),默认驱动可以省略。定义数据库连接需要用到的字符串。
用create_engine建立数据库引擎。
使用上下文管理器定义的scoped_session,建立会话。
为了使之后的数据库操作的代码能够自动进行事务处理,定义了上下文函数session_scope()。在Python中定义上下文函数的方法
是为其加入contextlib包中的contextmanager装饰器。在上下文函数中执行如下逻辑:在函数开始时建立数据库会话,此时会自动建立一个数据库事务;
当发生异常是回滚事务;当退出时关闭连接。在关闭连接时会自动进行事务处理*
SQLAlchemy 同样可以执行原生SQL对象
from sqlalchemy import create_engine
def exec_raw_sql(eng, sql):
with eng.connect() as con:
return list(con.execute(sql))
- exec_raw_sql 是自定义的函数,需要传入SQLAlchemy 数据库连接实例化的引擎,具体为
eng = create_engine(db_uri),con.execute返回的对象需要用list转化一下,因为返回的是数据库查询对象。
查询条件设置
SQLAlchemy 查询条件被称为过滤器
- 等值过滤器
session.query(Account).filter(Account.user_name == "Jackey")
session.query(Account).filter(Account.salary == 2000)
- 不等过滤器(!=,<,>,<=,>=)
session.query(Account).filter(Account.user_name != "Jackey")
session.query(Account).filter(Account.salary >= 2000)
- 模糊查询--like 仅支持字符串
session.query(Account).filter(Account.user_name.like('%i%'))
- 包括过滤器(in_)
session.query(Account).filter(Account.user_name.in_(['xiaohong','xiaoming','xiaoli']))
- 判断是否为空(is NULL, is not NULL)
空值NULL是数据库字段中比较特殊的值。在SQLAlchemy中支持对字段是否为空进行判断。判读时可以用等值,不等值过滤器筛选,亦可用is,isnot进行筛选。
session.query(Account).filter(Account.salary == None)
session.query(Account).filter(Account.salary.is_(None))
session.query(Account).filter(Account.salary != None)
session.query(Account).filter(Account.isnot(None))
- 非逻辑(~)
session.query(Account).filter(~Account.id.in_([1,3,5]))
- 与逻辑(and_)
session.query(Account).filter(Account.title=='Engineer',Account.salary=3000)
session.query(Account).filter(and_(Account.title=="engineer",Account.salary=3000))
- 或逻辑(or_)
session.query(Account).filter(or_(Account.title=="engineer",Account.salary=3000))
关系操作
SQLAlchemy 支持数据库模型的一对一,一对多,多对多关系。支持通过将各个表通过主键,外键联系起来。
以下是一个简单的数据表 E-R图映射,其中,class表与student表是一对多关系,class表与teacher表之间是多对多关系

将E-R图转化为SQLAlchemy模型定义的代码文件如下
from sqlalchemy import Table, Column, Integer, ForeignKey, String
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Class(Base):
__tablename__ = 'class'
class_id = Column(Integer, primary_key=True)
name= Column(String(50))
level = Column(Integer)
address = Column(String(50))
class_teachers = relationship("ClassTeacher", backref="class")
students = relationship("Student", backref="class")
class Student(Base):
__tablename__ = 'student'
student_id = Column(Integer, primary_key=True)
name= Column(String(50))
age = Column(Integer)
gender= Column(String(10))
address= Column(String(50))
class_id = Column(Integer, ForeignKey('class.class_id'))
class Teacher(Base):
__tablename__ = 'teacher'
teacher_id = Column(Integer, primary_key=True)
name= Column(String(50))
gender= Column(String(10))
telephone= Column(String(50))
address= Column(String(50))
class_teachers = relationship("ClassTeacher", backref="teacher")
class ClassTeacher(Base):
__tablename__ = 'class_teacher'
teacher_id = Column(Integer, ForeignKey('teacher.teacher_id'), primary_key=True)
class_id = Column(Integer,ForeignKey('class.class_id'),primary_key=True)
代码说明
外键设置:在列的定义中,为Column传入ForeignKey进行外键设置
class_id = Column(Integer, ForeignKey('class.class_id'))
关系设置:通过relationship关键字在父模型中建立对子表的引用,例如Class模型中的关系设置如下
students = relationship("Student", backref="class")
注意students 即student表中所有拥有相同class_id的记录的集合,SQLAlchemy中Class表的实例可直接通过students属性访问到。
class_=session.query(Class).filter(Class.name==u"三年二班").first()
for student in class_.students:
print u"学生姓名:%s, 年龄:%d" %(student.name, student.age)
另外,backref参数如果设置了,则表示同时设置了父表(一对多关系中的一)对子表的引用。
即student表的实例可以通过class属性访问与其关联的class记录。
多对多关系的使用,通过ClassTeacher表实现。其中分别设置模型Class和Teacher的外键,并且在父模型中设置相应的relationship实现。
多对多关系也可以想象成一个关联表,分别对两个父表实现了多对一的关系。班级与老师之间为多对多关系,如下代码可以打印特定班级所有老师的信息
class_=session.query(Class).filter(Class.name==u"三年二班").first()
for class_teacher in class_.class_teachers:
teacher = class_teacher.teacher
print u"老师姓名:%s, 电话:%s"%(teacher.name, teacher.telephone)
级联
级联是在一对多关系中父表对字表进行联动操作的数据库术语。因为父表与字表通过外键关联,所以对父表或字表的增删改查都会对另一张表也产生相应的
影响。
级联定义
SQLAlchemy 中的级联通过父表中的relationship属性定义cascade参数来实现,代码如下:
from sqlalchemy import Table, Column, Integer, ForeignKey, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref
Base = declarative_base()
class Class(Base):
__tablename__ = 'class'
class_id = Column(Integer, primary_key=True)
name= Column(String(50))
level = Column(Integer)
address = Column(String(50))
students = relationship("Student", backref="class_", cascade="all")
class Student(Base):
__tablename__ = 'student'
student_id = Column(Integer, primary_key=True)
name= Column(String(50))
age = Column(Integer)
gender= Column(String(10))
address= Column(String(50))
class_id = Column(Integer, ForeignKey('class.class_id'))
上述代码定义了class表和student表。一对多的关系由父表中的relationship属性students进行定义。relationship中的cascade属性
定义了要在该关系上实现的级联方法为"all", 其他的cascade属性有save_update,merge,expunge,delete,delete-orphan,refresh-expire,all
其中save_update,delete,delete_orphan与父表的数据变化有关,其他与session操作有关。多个cascade属性可以通过逗号分隔并同时赋值给
cascade。如
students = relationship("Student",backref="class_",cascade="save-update,merge,expunge")
SQLAlchemy 快速入门、基础知识的更多相关文章
- python快速入门基础知识
1.变量赋值与语句 #python 不需要手动指定变量类型.不需要分号 #To assign the value 365 to the variable days,we enter the varia ...
- Linux入门基础知识
注:内容系兄弟连Linux教程(百度传课:史上最牛的Linux视频教程)的学习笔记. Linux入门基础知识 1. Unix和Linux发展历史 二者就像父子关系,当然Unix是老爹.1965年,MI ...
- USB入门基础知识(转)
源:USB入门基础知识 相关名词: 主机(Host) 设备(Device) 接口(Interface) 管道(Pipe) 管道是主机与设备端点数据传输的连接通道,代表了主机的数据缓冲区与设备端点之间交 ...
- React Native 入门基础知识总结
中秋在家闲得无事,想着做点啥,后来想想,为啥不学学 react native.在学习 React Native 时, 需要对前端(HTML,CSS,JavaScript)知识有所了解.对于JS,可以看 ...
- Greenplum入门——基础知识、安装、常用函数
Greenplum入门——基础知识.安装.常用函数 2017年10月08日 22:03:09 在咖啡里溺水的鱼 阅读数:8709 版权声明:本文为博主原创,允许非商业性质转载但请注明原作者和出处 ...
- Java快速入门-03-小知识汇总篇(全)
Java快速入门-03-小知识汇总篇(全) 前两篇介绍了JAVA入门的一系小知识,本篇介绍一些比较偏的,说不定什么时候会用到,有用记得 Mark 一下 快键键 常用快捷键(熟记) 快捷键 快捷键作用 ...
- 1)Linux程序设计入门--基础知识
)Linux程序设计入门--基础知识 Linux下C语言编程基础知识 前言: 这篇文章介绍在LINUX下进行C语言编程所需要的基础知识.在这篇文章当中,我们将 会学到以下内容: 源程序编译 Makef ...
- Scala快速入门 - 基础语法篇
本篇文章首发于头条号Scala快速入门 - 基础语法篇,欢迎关注我的头条号和微信公众号"大数据技术和人工智能"(微信搜索bigdata_ai_tech)获取更多干货,也欢迎关注我的 ...
- React入门---基础知识-大纲-1
-----------------在慕课网学习react入门笔记-------------- ---------博主边学边记录,手把手进行学习及记录---------- --------------- ...
- CodeMix入门基础知识
CodeMix在线订购年终抄底促销!火爆开抢>> CodeMix入门 CodeMix是一个Eclipse插件,可以直接从Eclipse访问VS Code和为Code OSS构建的附加扩展的 ...
随机推荐
- 学会谈判zz
经常有人问我,为什么谈判到你手里就变得那么容易?你有什么诀窍?其实只要是谈判,涉及双方利益,就绝不会轻松.之所以能谈判成功,仔细想想秘诀无非是两个字:“双赢”.要想成功,就要双方都受益.如果你一开始就 ...
- 解决Oracle+Mybatis批量插入报错:SQL 命令未正确结束
Mybatis批量插入需要foreach元素.foreach元素有以下主要属性: (1)item:集合中每一个元素进行迭代时的别名. (2)index:指定一个名字,用于表示在迭代过程中,每次迭代到的 ...
- 微信小程序之下拉加载和上拉刷新
微信小程序下拉加载和上拉刷新两种实现方法 方法一:onPullDownRefresh和onReachBottom方法实现小程序下拉加载和上拉刷新 首先要在json文件里设置window属性 ...
- JDBC连接SQL Server数据库
测试环境 数据库:SQL Server 2008 R2,创建数据库名:TestDemo,表:User,字段如下: 字段 字段 id UName UPass sqljdbc.jar下载地址:依赖的J ...
- Ng第三课:线性代数回顾(Linear Algebra Review)
3.1 矩阵和向量 3.2 加法和标量乘法 3.3 矩阵向量乘法 3.4 矩阵乘法 3.5 矩阵乘法的性质 3.6 逆.转置 3.1 矩阵和向量 如图:这个是 4×2 矩阵,即 4 行 ...
- 使用freemarker导出word
最近需要将jsp部分页面导出为word文件,环境是Spring+SpringMVC+Hibernate. 我使用的是FreeMarker模板引擎来完成.这是FreeMarker的中文参考手册,感兴趣的 ...
- java基础-day14
第01天 java面向对象 今日内容介绍 u 接口 u 匿名对象&final u 多态 第1章 接口 1.1 接口的概述 接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的 ...
- jQuery插件初级练习5
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...
- ASP.NET Web API 框架研究 服务容器 ServicesContainer
ServicesContainer是一个服务的容器,可以理解为—个轻量级的IoC容器,其维护着一个服务接口类型与服务实例之间的映射关系,可以根据服务接口类型获取对应的服务实例.构成ASP.NET We ...
- Azure DevOps Server: 使用Rest Api获取拉取请求Pull Request中的变更文件清单
需求: Azure DevOps Server 的拉取请求模块,为开发团队提供了强大而且灵活的代码评审功能.拉取请求中变更文件清单,对质量管理人员,是一个宝贵的材料.质量保障人员可以从代码清单中分析不 ...