数据库

SQL数据库

关系型数据库把数据存储在表中。表的列数是固定的。行数的可变的。列定义表所表示的实体的数据属性。表中的行定义各列对应的真实数据。

表中有个特殊的列,称为主键(primary key),其值为表中各行的唯一标识符。表中还可以有称为外键(foregin key)的列,引用同一个表或不同表中某行的主键。行之间的这种联系称为关系,这时关系型数据库模型的基础。

NoSQL数据库

NoSQL数据库一般使用集合代替表,因为它不遵循上述所说的关系。NoSQL数据库一般使用集合代替表,使用文档代替记录。

SQL数据库擅长用高效且紧凑的形式存储结构化数据。这种数据库需要花费大量精力保证数据的一致性。NoSQL数据库放宽了对这种一致性的要求,从而获得性能上的优势。

Python数据库框架

Flask并不限制你使用何种类型的数据库包,因此可以根据自己的喜欢选择使用MySQL,Postgres,SQLite,Redis,MongoDB或者CouchDB

如果这些都无法满足需求,还有一些数据库抽象层代码包供选择,例如SQLAlchemy和MongoEngine.你可以使用这些抽象包直接处理高等级的Python对象,而不用处理如表,文档或查询语言此类的数据库实体。

选择数据库框架时,要考虑很多因素:
1.易用性
如果直接比较数据库引擎和数据库抽象层,显然后者取胜。抽象层,也被称为对象关系映射(ORM)或对象文档映射(ODM),在用户不知觉的情况下把高层的面向对象操作转换成低层的数据库指令

2.性能

3.可移植性
选择数据库时,必须考虑其是否能在你的开发平台和生产平台中使用

4.Flask集成度

本书选择使用的数据库框架是Flask-SQLAlchemy

使用Flask-SQLAlchemt管理数据库

Flask-SQLAlchemy是一个Flask扩展,简化了在Flask程序中使用SQLAlchemy的操作。SQLAlchemy是一个很请打的关系型数据库框架,支持多种数据库后台。SQLAlchemy提供了高层ORM,也提供了使用数据库原生SQL的低层功能。

表5-1 FLask-SQLAlchemy数据库URL
数据库引擎 URL
MySQL mysql://username:password@hostname/database
Postgres postgresql://username:password@hostname/database
SQLite(Unix) sqlite:////absolute/path/to/database
SQLite(Windows) sqlite:///c:/absolute/path/to/database

hostname表示MySQL服务所在的主机,可以是本地主机,也可以是远程服务器。数据库服务器上可以托管多个数据库,因此database表示要使用的数据库名。如果数据库需要进行认证,username和password表示数据库用户密令。

#配置数据库
from flask.ext.sqlalchemy import SQLAlchemy
basedir = os.path.abspaht(os.path.dirname(__file__))
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI']=\
    'sqlite:///'+os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN']=True
db= SQLAlchemy(app)#db对象是SQLAlchemy类的实例,表示程序使用的数据库,同时还获得了Flask-SQLAlchemy提供的所有功能。

定义模型(model)

模型这个术语表示程序使用的持久化实体。在ORM中,模型一般是一个Python类,类中的属性对应数据库表中的列。

class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    
    def __repr__(self):
         return '<Role % r>' % self.name
class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
def __repr__(self):
    return '<User % r>' % self.username
#类变量__tablename__定义在数据库中使用的表名。

表5-2 最常用的SQLAlchemy列类型
类型名 Python类型 说 明
Integer int 普通整数,一般是 32 位
SmallInteger int 取值范围小的整数,一般是 16 位
BigInteger int 或 long 不限制精度的整数
Float float 浮点数
Numeric decimal.Decimal 定点数
String str 变长字符串
Text str 变长字符串,对较长或不限长度的字符串做了优化
Unicode unicode 变长 Unicode 字符串
UnicodeText unicode 变长 Unicode 字符串,对较长或不限长度的字符串做了优化
Boolean bool 布尔值
Date datetime.date 日期
Time datetime.time 时间
DateTime datetime.datetime 日期和时间
Interval datetime.timedelta 时间间隔
Enum str 一组字符串
PickleType 任何 Python 对象 自动使用 Pickle 序列化
LargeBinary str 二进制文件
db.Column 中其余的参数指定属性的配置选项。

表5-3 最常使用的SQLAlchemy列选项
选项名 说 明
primary_key 如果设为 True ,这列就是表的主键
unique 如果设为 True ,这列不允许出现重复的值
index 如果设为 True ,为这列创建索引,提升查询效率
nullable 如果设为 True ,这列允许使用空值;如果设为 False ,这列不允许使用空值
default 为这列定义默认值

关系

关系型数据库使用关系把不同表中的行联系起来。

class Role(db.MOdel):
    #...
    users = db.relationship('User',backref='role')

class User(db.Model):
    #...
    role_id = db.Column(db.Integer,db.ForeignKey('roles.id'))

常用的SQLAlchemy关系选项
backref 在关系的另一个模型中添加反向引用
orimaryjoin 明确指定两个模型之间使用的联结条件
lazy 指定如何加载相关记录。
uselist 如果设为 Fales ,不使用列表,而使用标量值
order_by 指定关系中记录的排序方式
secondary 指定 多对多 关系中关系表的名字
secondaryjoin SQLAlchemy 无法自行决定时,指定多对多关系中的二级联结条件

最复杂的关系类型是多对多,需要用到第三张表,这个表称为关系表。

数据库操作

db.create_all()#根据模型类(上面定义的两个类User,Role)创建数据库。
db.drop_all()#删除旧表

通过数据库会话(db.session)管理对数据库所做的改动
db.session.rollback(),添加到数据库会话中的所有对象都会还原道它们在数据库时的状态。

db.sessoin.delete()
db.session.commit()

查询行

Flask-SQLAlchemy为每个模型类都提供了query对象。最基本的模型查询是取回对应表中的所有记录:
Role.query.all()
User.query.all()
使用过滤器可以配置query对象进行更精确的数据库查询。
User.query.fliter_by(role = user_role).all()
filter_by是查询过滤器, all是查询执行函数
若要查看SQLAlchemy为查询生成的原生SQL查询语句,只需把query对象转换乘字符串:
str(User.query.filter_by(role=user_role))

表5-5 常用的SQLAlchemy查询过滤器
过滤器 说 明
filter() 把过滤器添加到原查询上,返回一个新查询
filter_by() 把等值过滤器添加到原查询上,返回一个新查询
limit() 使用指定的值限制原查询返回的结果数量,返回一个新查询
offset() 偏移原查询返回的结果,返回一个新查询
order_by() 根据指定条件对原查询结果进行排序,返回一个新查询
group_by() 根据指定条件对原查询结果进行分组,返回一个新查询

表5-6 最常使用的SQLAlchemy查询执行函数
方 法 说 明
all() 以列表形式返回查询的所有结果
first() 返回查询的第一个结果,如果没有结果,则返回 None
first_or_404() 返回查询的第一个结果,如果没有结果,则终止请求,返回 404 错误响应
get() 返回指定主键对应的行,如果没有对应的行,则返回 None
get_or_404() 返回指定主键对应的行,如果没找到指定的主键,则终止请求,返回 404 错误响应
count() 返回查询结果的数量
paginate() 返回一个 Paginate 对象,它包含指定范围内的结果

在视图函数中操作数据库

使用FLask-Migrate实现数据库迁移

在开发程序的过程中,你会发现有时需要修改数据库模型,而且修改之后还需要更新数据库。

更新表的更好方法是使用数据库迁移框架。源码版本控制工具可以跟踪源码文件的变化,类似地,数据库迁移框架能跟踪数据库模式的变化,然后增量式的把变化应用到数据库中。

SQLAlchemy的主力开发人员编译了一个迁移框架,称为Alembic,除了直接使用Alembic之外,FLask程序还可使用FLask-Migrate扩展。这个扩展对Alembic做了轻量级包装

配置Flask-Migrate

from flask.ext.migrate import Migrate,MigrateCommand
#...

migrate = Migrate(app,db)
manager.add_command('db',MigrateCommand)

posted @ 2018-02-15 11:58  blog_hfg  阅读(187)  评论(0)    收藏  举报