Flask-SQLAlchemy 配置,处理对象-关系,一对多,多对多
ORM
(Object Relational Mapper) 对象关系映射。指将面对对象得方法映射到数据库中的关系对象中。 Flask-SQLAlchemy是一个Flask扩展,能够支持多种数据库后台,我们可以不需要关心SQL的处理细节,操作数据库,一个基本关系对应一个类,而一个实体对应类的实例对象,通过调用方法操作数据库。Flask-SQLAlchemy
有很完善的文档。Flask-SQLAlchemy
是通过URL指定数据库的连接信息的。 初始化的两种方法如下(以连接Mysql数据库为例):
from flask_sqlalchemy import SQLAlchemy
from flask import FLask
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] =
"mysql://root:12345@localhost/test"
db = SQLAlchemy(app)
或者
from flask_sqlalchemy import SQLAlchemy
from flask import FLask
db = SQLAlchemy() def create_app():
app = Flask(__name__)
db.init_app(app)
return app
两者的区别在于:第一种不需要启动flask的app_context
;但是第二种方法则需要,因为可能会创建多个Flask应用,但是我的理解是一般地开发时,Flask实例是延迟创建的,因为在运行时难以修改配置信息,这种方法符合这种情况。Flask-SQLAlchemy
的则需要在Flask.config
中声明。更多详细信息需要查配置。例如配置信息中指出SQLAlchemy
是可以绑定多个数据库引擎。再例如:在新浪SAE云平台开发个人博客时遇到gone away
这种问题就需要添加SQLALCHEMY_POOL_RECYCLE
信息,新浪开发者文档中有说明。
SQLALchemy处理 对象->关系
SQLAlchemy是如何处理对象到关系的?实例来自于数据库系统概论内容。
简单实例
创建学生students表
class Student(db.Model):
__tablename__ = 'students' #指定表名
sno = db.Column(db.String(10), primary_key=True)
sname = db.Column(db.String(10))
sage = db.Column(db.Integer)
API文档说明创建对象需要继承db.Model类
关联数据表项,db.Model类
继承Query类
提供有数据查询方法;__tablename__
指定数据库的表名,在Flask-SQLAlchemy
中是可省的。Column
指定表字段。
SQLAlchemy支持字段类型有:
类型名 | python类型 | 说明 |
---|---|---|
Integer | int | 普通整数,32位 |
Float | float | 浮点数 |
String | str | 变长字符串 |
Text | str | 变长字符串,对较长字符串做了优化 |
Boolean | bool | 布尔值 |
PickleType | 任何python对象 | 自动使用Pickle序列化 |
来源于Simple Example,Flask Web开发有更详细的内容。 其余的参数指定属性的配置选项,常用的配置选项如下:
选项名 | 说明 |
---|---|
primarykey | 如果设为True,表示主键 |
unique | 如果设为True,这列不重复 |
index | 如果设为True,创建索引,提升查询效率 |
nullable | 如果设为True,允许空值 |
default | 为这列定义默认值 |
如使用default
默认time属性如下:
time = db.Column(db.Date, default=datetime.utcnow)
说明default
可以接受lambda
表达式。
一对多
按创建单张表的方法,创建学院Deptment表
class Deptment(db.Model):
__tablename__ = 'deptments'
dno = db.Column(db.Integer, primary_key=True)
dname = Sname = db.Column(db.String(10),index=True)
学院和学生是一对多的关系。Flask-SQLAlchemy
是通过db.relationship()
解决一对多的关系。在Dept中添加属性,代码如下:
class Deptment(db.Model):
...
students = db.relationship('Student', backref='dept') class Student(db.Model):
...
dept_no = db.Column(db.Integer, db.ForeignKey('deptments.dno'))
表的外键由db.ForeignKey
指定,传入的参数是表的字段。db.relations
它声明的属性不作为表字段,第一个参数是关联类的名字,backref
是一个反向身份的代理,相当于在Student类中添加了dept的属性。例如,有Deptment实例dept和Student实例stu。dept.students.count()
将会返回学院学生人数;stu.dept.first()
将会返回学生的学院信息的Deptment类实例。一般来讲db.relationship()
会放在一
这一边。
多对多
多对多的关系可以分解成一对多关系,例如:学生选课,学生与课程之间的关系:
sc = db.Table('sc',
db.Column('sno', db.String(10), db.ForeignKey('students.sno'))
db.Column('cno',db.String(10), db.ForeignKey('courses.cno'))
) Class Course(db.Model):
__tablename__ = 'courses'
cno = db.Column(db.String(10), primary_key=True)
cname = db.Column(db.String(10), index=True)
students = db.relationship('Student',
secondary=sc,
backref=db.backref('course',lazy='dynamic'),
lazy='dynamic'
)
sc
表由db.Table
声明,我们不需要关心这张表,因为这张表将会由SQLAlchemy
接管,它唯一的作用是作为students表和courses表关联表,所以必须在db.relationship()
中指出sencondary
关联表参数。lazy
是指查询时的惰性求值的方式,这里有详细的参数说明,而db.backref
是声明反向身份代理,其中的lazy
参数是指明反向查询的惰性求值方式,SQLAlchemy
鼓励这种方式声明多对多的关系。
但是如果关联表中有自定义的字段,如sc表中添加成绩字段则需要更改表声明方式,将sc
更改为继承db.Model
的对象并设置sc:courses = 1:n
和sc:student = 1:n
的关系。
SQLALchemy处理 关系->对象
Flask-SQLAlchemy查询中有详细的说明。创建关系后该如何查询到对象?
SQLAlchemy有查询过滤器如下:
过滤器 | 说明 |
---|---|
filter() | 把过滤器添加到原查询,返回新查询 |
filter_by() | 把等值过滤器添加到原查询,返回新查询 |
limit() | 使用指定值限制原查询返回的结果数量,返回新查询 |
offset() | 偏移原查询返回的结果,返回新查询 |
order_by() | 排序返回结果,返回新查询 |
groupby() | 原查询分组,返回新查询 |
这些过滤器返回的结果都是一个新查询,我的理解是这些查询其实是生成的SQL语句,lazy
的惰性求值方式也体现在查询上,而这些语句不能生成需要查询的对象,需要调用其他的方法生成对象。
SQL查询执行函数:
方法 | 说明 |
---|---|
all() | 以列表形式返回结果 |
first() | 返回第一个结果,如果没有返回None |
first_or_404() | 返回第一个结果,如果没有抛出404异常 |
get() | 返回主键对应记录,没有则返回None |
get_or_404() | 返回主键对应记录,如果没有抛出404异常 |
count() | 返回查询结果数量 |
paginate() | 返回paginate对象,此对象用于分页 |
Flask-SQLAlchemy 配置,处理对象-关系,一对多,多对多的更多相关文章
- MyBatis加强(1)~myBatis对象关系映射(多对一关系、一对多关系)、延迟/懒加载
一.myBatis对象关系映射(多对一关系.一对多关系) 1.多对一关系: ---例子:多个员工同属于一个部门. (1)myBatis发送 额外SQL: ■ 案例:员工表通过 dept_id 关联 部 ...
- SQLAlchemy的增删改查 一对多 多对多
Models只是配置和使用比较简单,因为是Django自带的ORM框架,所以兼容性不行,所以出现了SQLAlchemy,SQLAlchemy是比较全面的ORM框架,它可以在任何使用SQL查询时使用 以 ...
- hibernate对象关系实现(三)多对多实现
单向n-n:(catogory-item)一个类别对应多个条目,一个条目对应多个类别 a.以类别类中有条目的集合的引用为例: b.数据库中的体现:建立一个新表,以类别和条目的主键关联的外键做新表的联合 ...
- 2018.11.4 Hibernate中一对、多对多的关系
简单总结一下 多表关系 一对多/多对一 O 对象 一的一方使用集合. 多的一方直接引用一的一方. R 关系型数据库 多的一方使用外键引用一的一方主键. M 映射文件 一: 多: 操作: 操作管理级别属 ...
- flask SQLAlchemy中一对多的关系实现
SQLAlchemy是Python中比较优秀的orm框架,在SQLAlchemy中定义了多种数据库表的对应关系, 其中一对多是一种比较常见的关系.利用flask sqlalchemy实现一对多的关系如 ...
- hibernate对象关系实现(一)一对多
hibernate是对jdk一个封装工具,实现对象和数据库之间数据映射.使用时涉及到四个问题:a.对象之间的关系在类中的体现:b,对象关系对应的数据库中表之间体现:c.实现a,b在hibernate的 ...
- Hibernate学习笔记三:对象关系映射(一对一,一对多,多对一,多对多)
如需转载,请说明出处:http://www.cnblogs.com/gudu1/p/6895610.html Hibernate通过关系映射来表示数据库中表与表之间的关系,关系映射可以通过两种方式:配 ...
- Hibernate:对象关系映射(一对一,一对多,多对一,多对多)
如需转载,请说明出处:http://www.cnblogs.com/gudu1/p/6895610.html Hibernate通过关系映射来表示数据库中表与表之间的关系,关系映射可以通过两种方式:配 ...
- $Django setting.py配置 ,GET、POST深入理解,三件套,orm对象关系映射简介
1 django中app的概念: 大学:----------------- 项目 信息学院 ----------app01 物理学院-----------app02 ****强调***:创建的每一 ...
随机推荐
- POJ 1679 The Unique MST:次小生成树【倍增】
题目链接:http://poj.org/problem?id=1679 题意: 给你一个图,问你这个图的最小生成树是否唯一. 题解: 求这个图的最小生成树和次小生成树.如果相等,则说明不唯一. 次小生 ...
- windows下安装 postgresql
1. 下载PostgreSQL的源代码.解压. 2. 在Windows平台下编译需要跳过一个权限的检测,否则在编译的时候可能会出现错误. 在\src\backend\main\main.c文件中将 ...
- ACM学习历程—HDU5422 Rikka with Graph(贪心)
Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, so he ...
- bzoj 1242 弦图判定 MCS
题目大意: 给定一张无向图,判断是不是弦图. 题解: 今天刚学了<弦图与区间图> 本来写了一个60行+的学习笔记 结果因为忘了保存重启电脑后被还原了... 那就算了吧. MCS最大势算法, ...
- C/C++面试题总结(1)
首先说一下,这些东西,有的是必须掌握的,有的是面试时你讲出来就是闪光点.自己把握.把握不好的都搞懂.实在不行背下来. 由于时间关系,总结的比较随意,有的就直接贴链接了,希望理解一下. 第一篇:基础(必 ...
- JS通过经纬度计算两个地方的距离
1 主要原理: Lat1 Lung1 表示A点纬度和经度,Lat2 Lung2 表示B点纬度和经度: a=Lat1 – Lat2 为两点纬度之差 b=Lung1 -Lung2 为两点经度之差: 63 ...
- 洛谷 4178 Tree——点分治
题目:https://www.luogu.org/problemnew/show/P4178 点分治.如果把每次的 dis 和 K-dis 都离散化,用树状数组找,是O(n*logn*logn),会T ...
- web攻击之二:CSRF跨站域请求伪造
CSRF是什么? (Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式,它在 2007 年曾被列为互联网 20 大安全隐患之一,也被称为“One Click ...
- 二 lambda表达式
1:lambda写的好可以极大的减少代码冗余,同时可读性也好过冗长的内部类,匿名类. 2: lambda表达式配合Java8新特性Stream API可以将业务功能通过函数式编程简洁的实现. 3: l ...
- 问题:C# Dictionary嵌套使用;结果:嵌套Dictionary添加 , C#2.0泛型详细介绍
Dictionary<int, Dictionary<string, string>> dict1 = new Dictionary<int, Dictionary< ...