ORM
(Object Relational Mapper) 对象关系映射。指将面对对象得方法映射到数据库中的关系对象中。
Flask-SQLAlchemy是一个Flask扩展,可以支持多种数据库后台,咱们能够不须要关心SQL的处理细节,操做数据库,一个基本关系对应一个类,而一个实体对应类的实例对象,经过调用方法操做数据库。
Flask-SQLAlchemy
有很完善的文档。
Flask-SQLAlchemy
是经过URL指定数据库的链接信息的。 初始化的两种方法以下(以链接Mysql数据库为例):python
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)
或者mysql
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
信息,新浪开发者文档中有说明。sql
SQLAlchemy是如何处理对象到关系的?实例来自于数据库系统概论内容。数据库
建立学生students表flask
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
指定表字段。segmentfault
SQLAlchemy支持字段类型有:app
类型名 | 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
表达式。spa
按建立单张表的方法,建立学院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
的关系。
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对象,此对象用于分页 |