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 查询条件被称为过滤器

  1. 等值过滤器
session.query(Account).filter(Account.user_name == "Jackey")
session.query(Account).filter(Account.salary == 2000)
  1. 不等过滤器(!=,<,>,<=,>=)
session.query(Account).filter(Account.user_name != "Jackey")
session.query(Account).filter(Account.salary >= 2000)
  1. 模糊查询--like 仅支持字符串
session.query(Account).filter(Account.user_name.like('%i%'))
  1. 包括过滤器(in_)
session.query(Account).filter(Account.user_name.in_(['xiaohong','xiaoming','xiaoli']))
  1. 判断是否为空(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))
  1. 非逻辑(~)
session.query(Account).filter(~Account.id.in_([1,3,5]))
  1. 与逻辑(and_)
session.query(Account).filter(Account.title=='Engineer',Account.salary=3000)
session.query(Account).filter(and_(Account.title=="engineer",Account.salary=3000))
  1. 或逻辑(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 快速入门、基础知识的更多相关文章

  1. python快速入门基础知识

    1.变量赋值与语句 #python 不需要手动指定变量类型.不需要分号 #To assign the value 365 to the variable days,we enter the varia ...

  2. Linux入门基础知识

    注:内容系兄弟连Linux教程(百度传课:史上最牛的Linux视频教程)的学习笔记. Linux入门基础知识 1. Unix和Linux发展历史 二者就像父子关系,当然Unix是老爹.1965年,MI ...

  3. USB入门基础知识(转)

    源:USB入门基础知识 相关名词: 主机(Host) 设备(Device) 接口(Interface) 管道(Pipe) 管道是主机与设备端点数据传输的连接通道,代表了主机的数据缓冲区与设备端点之间交 ...

  4. React Native 入门基础知识总结

    中秋在家闲得无事,想着做点啥,后来想想,为啥不学学 react native.在学习 React Native 时, 需要对前端(HTML,CSS,JavaScript)知识有所了解.对于JS,可以看 ...

  5. Greenplum入门——基础知识、安装、常用函数

    Greenplum入门——基础知识.安装.常用函数 2017年10月08日 22:03:09 在咖啡里溺水的鱼 阅读数:8709    版权声明:本文为博主原创,允许非商业性质转载但请注明原作者和出处 ...

  6. Java快速入门-03-小知识汇总篇(全)

    Java快速入门-03-小知识汇总篇(全) 前两篇介绍了JAVA入门的一系小知识,本篇介绍一些比较偏的,说不定什么时候会用到,有用记得 Mark 一下 快键键 常用快捷键(熟记) 快捷键 快捷键作用 ...

  7. 1)Linux程序设计入门--基础知识

    )Linux程序设计入门--基础知识 Linux下C语言编程基础知识 前言: 这篇文章介绍在LINUX下进行C语言编程所需要的基础知识.在这篇文章当中,我们将 会学到以下内容: 源程序编译 Makef ...

  8. Scala快速入门 - 基础语法篇

    本篇文章首发于头条号Scala快速入门 - 基础语法篇,欢迎关注我的头条号和微信公众号"大数据技术和人工智能"(微信搜索bigdata_ai_tech)获取更多干货,也欢迎关注我的 ...

  9. React入门---基础知识-大纲-1

    -----------------在慕课网学习react入门笔记-------------- ---------博主边学边记录,手把手进行学习及记录---------- --------------- ...

  10. CodeMix入门基础知识

    CodeMix在线订购年终抄底促销!火爆开抢>> CodeMix入门 CodeMix是一个Eclipse插件,可以直接从Eclipse访问VS Code和为Code OSS构建的附加扩展的 ...

随机推荐

  1. Python开课复习-10/17

    pickle是一个用来序列化的模块序列化是什么?指的是将内存中的数据结构转化为一种中间格式 并存储到硬盘上 反序列化?将硬盘上存储的中间格式数据在还原为内存中的数据结构 为什么要序列化?就是为了将数据 ...

  2. 2019.01.08 bzoj3809: Gty的二逼妹子序列(莫队+权值分块)

    传送门 题意:多组询问,问区间[l,r]中权值在[a,b]间的数的种类数. 看了一眼大家应该都知道要莫队了吧. 然后很容易想到用树状数组优化修改和查询做到O(mnlogamax)O(m\sqrt nl ...

  3. JAVA遇上HTML-----JSP 篇基本概念

    Java Web简介 1.什么是WEB应用程序: Web应用程序是一种可以通过Web访问的应用程序.Web应用程序的一个最大好处是用户很容易访问应用程序.用户只需要有浏览器即可,不需要再安装其他软件. ...

  4. mysql 在linux下的完整安装过程

    1.下载RPM包 https://cdn.mysql.com//archives/mysql-5.7/mysql-5.7.20-1.el7.x86_64.rpm-bundle.tar 2.先使用命令删 ...

  5. Le Chapitre X

    Il se trouvait dans la région des astéroïdes 325, 326, 327, 328, 329 et 330. Il commença donc par le ...

  6. hadoop集群的三种运行模式

    单机(本地)模式: 这种模式在一台单机上运行,没有分布式文件系统,而是直接读写本地操作系统的文件系统.在单机模式(standalone)中不会存在守护进程,所有东西都运行在一个JVM上.这里同样没有D ...

  7. error C2143: syntax error : missing ';' before 'type'

    许久之前,就想看看C和C++,看看这两种神奇的编程语言,但是一直被这样或者那样的琐事给耽搁了(狂喷自己的拖延症). 今天翻开自己的移动硬盘找到一本古老的书籍:<The C Programming ...

  8. java的静态内部类

    只是一个简单的记录.因为一直排斥java这个东西.java跟c++比是很不错的一个语言,至少内存管理这么麻烦的东西不用操心了.但是和不断崛起的脚本语言比起来,效率差的太多.无论如何做android还是 ...

  9. app.json

    APP.JSON 文件来对微信小程序进行全局配置,决定页面文件的路径.窗口表现.设置网络超时时间.设置多 TAB 等.相当于iOS开发中的AppDelegate 注意该文件不可添加任何注释. {   ...

  10. (多线程dp)Matrix (hdu 2686)

    http://acm.hdu.edu.cn/showproblem.php?pid=2686     Problem Description Yifenfei very like play a num ...