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构建的附加扩展的 ...
随机推荐
- PHP实现图片批量压缩
set_time_limit(0); global $source_dir; global $target_dir; $source_dir = "D:/images/";//目标 ...
- 范围for循环(c++11)
1.概念 1)c++11新标准下用范围for循环来遍历序列 2)使用范围for循环时,如果要修改序列中的元素,则必须把循环变量定义成引用类型: int main() { string s = &quo ...
- VSCode的终端修改
快速打开VSCode的快捷键是:Ctrl + `(反引号) 转自:https://blog.csdn.net/u013517122/article/details/82776607 因本人实在忍受不了 ...
- 【慕课网实战】Spark Streaming实时流处理项目实战笔记十之铭文升级版
铭文一级: 第八章:Spark Streaming进阶与案例实战 updateStateByKey算子需求:统计到目前为止累积出现的单词的个数(需要保持住以前的状态) java.lang.Illega ...
- 19) maven 项目结构:聚集
Project Aggregation [,æɡrɪ'ɡeɪʃən] https://maven.apache.org/guides/introduction/introduction-to-the- ...
- iptables简单应用
可以修改/etc/rc.d/boot.local让规则重启后也能生效,如: /sbin/iptables -F /sbin/iptables -A INPUT -i eth0 -p tcp --spo ...
- MySQL数据库与表的增删改查
1.值库管理 1.1 查询所有值库 show databases; 1.2 创建一个值库 create database 值库名称 default character set 编码格式名称; 1.3 ...
- Javaweb异常提示信息统一处理
Java异常封装(自己定义错误码和描述,附源码) 2016年01月29日 22:30:54 小宝鸽 阅读数:23262 标签: java异常 更多 个人分类: Java基础 所属专栏: Java工作实 ...
- poj 3013 最短路变形
http://poj.org/problem?id=3013 给出n个点,m个边.给出每个点的权值,每个边的权值.在m条边中选n-1条边使这n个点成为一棵树,root=1,求这棵树的最小费用,费用=树 ...
- iOS笔记之UIKit_UISlider/UIStepper/UISwitch
- (void)viewDidLoad { [super viewDidLoad]; self.sp = [[UIStepper alloc]init]; //设置计步器的位置 self.sp.cen ...