Flask数据库学习

数据库学习

@(Flask)

  • 关系型数据库(SQL数据库)
  • 文档数据库和键值对数据库 (NoSQL)

SQL数据库

是关键。用表可以模拟程序中不同的实体。

  • 主键:各行的唯一标识符。
  • 外键:引用同一个表或不同表中的某行的主键。

表的列是固定的,所以这个可以对应到程序中的属性值。

关系型数据库复杂的地方在于联表查询。

NoSQL数据库

一般使用集合代替表。
使用文档代替记录。

NoSQL的设计方式使得联结变得困难。

所以NoSQL的设计很多地方需要反规范化操作,才能保证效率,但是数据重复是难以避免的了。

SQL or NoSQL

SQL数据库擅长处理:高效且紧凑的形式存储结构化数据。这种数据库需要花费大量精力保证数据库的一致性

NoSQL数据库:放宽了对一致性的要求,获得了性能上的优势。

划重点:中小程序来说,SQL和NoSQL数据库都OK,且性能相当。

Python的数据库框架

Flask不限制使用何种类型的数据库包

  • MySQL
  • Postgres
  • SQLite
  • Redis
  • MonogoDB
  • CouchDB

这些具体的数据库包。

数据库抽象层代码包

  • SQLAlchemy
  • MongoEngine

通过这些包可以处理高等级的Python对象。

选择考量因素

  • 易用性:将高层的面向对象的操作转换为数据路指令。
    • ORM : 对象关系映射
    • ODM:对象文档映射
  • 性能
  • 可移植性
  • Flask集成度:专门为Flask开发的扩展是首选。

Flask-SQLAlchemy

强大的关系型数据库框架。且提供了ORM,也有原生的SQL功能。

安装pip install flask-sqlalchemy

数据库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

以MySQL为例,hostname是MySQL服务所在的主机
可以是:

  • localhost
  • 远程服务器

数据库服务器上可以托管多个数据库,所以要指定databasename

可以看到SQLite没有hostnameusername, password,因为SQLite不用服务器,是本地的数据库服务,安卓手机就用的是SQLite数据库。


from flask_sqlalchemy import SQLAlchemy #引入数据库管理包
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir,'data.sqlite')
db = SQLAlchemy(app)

db是SQLAlchemy类实例,表示的就是程序使用的数据库,通过db可以获得SQLAlchemy提供的所有功能。

定义模型

模型的含义:程序使用的持久化实体。

一般来说,数据库的天然属性就是持久化。

ORM下,模型是一个Python类,类的属性对应到数据库表中的列。

SQLAlchemy创建的数据库实例为模型提供了:

  • 一个基类
  • 一系列辅助类和辅助函数

用于定义模型的结构。

#定义模型
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 '' % self.name

类变量__tablename__定义在数据库中说那个的表名。

db.Column()类构造函数参数:

  • 第一个参数是数据库列和模型属性的类型
  • 第二个参数是可选配置选项

第一个参数类型不列举了,重点看第二个可选参数。

  • primary_key 设置为True,表示这是主键
  • unique 设置为True,表示这列不允许出现重复的值
  • index 设置为True,为这列创建索引,提升查询效率
  • nullable 设置为True,允许使用空值,反之,不允许用空值
  • default 定义默认值

__repr__()函数返回一个具有可读性的字符串表示模型,用于调试和测试

关系

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

#在Role类中定义
users = db.relationship('User',backref='role')
#role_id位于users表中,这个是外键
role_id = db.Column(db.Integer,db.ForeignKey('roles.id'))

db.relationship()第一个参数表明这个关系的另一端是哪个模型,如果模型尚未定义,可使用字符串形式执行。

backref参数向User模型中添加一个role属性。从而定义反向关系:通过这个属性可以替代role_id访问Role模型。此时可以获取的是模型对象,不是外键的值。

注:关于反向关系的理解,可以点击参考相关解释。

定义关系时常用的配置选项:

  • backref : 在关系的另一个模型中添加反向引用
  • primaryjoin : 明确指定两个模型之间使用的联结条件,只在模棱两可的关系中需要指定。
  • lazy : 指定如何加载相关记录。可选值有:
    • select 首次访问时按需加载
    • immediate 源对象加载后就加载
    • joined 加载记录但使用联结
    • subquery 立即加载,但使用子查询
    • noload 永不加载
    • dynamic 不加载记录,但提供加载记录的查询
  • uselist 若设为false,不使用列表,而使用标量值
  • order_by 指定关系中记录的排序方式
  • secondary 指定多对关系中关系表的名字
  • secondaryjoin SQLAlchemy无法自行决定时,指定多对多关系中的二级联结条件

注:上面这些不是特别清晰,需要在实例中阐述。

创建表

  • 根据模型创建数据库

方法:db.create_all()函数

python hello.py shell
>>> from hello import db
>>> db.create_all()

删除旧表:db.drop_all()

插入行
#同样在shell下
>>> from hello import Role, User
>>> admin_role = Role(name='Admin')
>>> mod_role = Role(name='Moderator')
>>> user_role = Role(name='User')
>>> user_john = User(username='john',role=admin_role)
>>> user_susan = User(username='susan',role=user_role)

修改行

>>> admin_role.name = 'Administrator'
>>> db.session.add(admin_role)
>>> db.session.commit()

删除行

>>> db.session.delete(mod_role)
>>> db.session.commit()

查询行

SQLAlchemy为每个模型类都提供给了query对象

最基本的查询是:Role.query.all()将返回表中的所有记录。

自然这个是很粗糙的,需要加条件过滤

过滤器

进行更精确的数据库查询。

User.query.filter_by(role=user_role).all()

可以很方便查询SQLAlchemy生成的原生SQL查询语句:

>>> str(User.query.filter_by(role=user_role))

将得到原生的SQL语句。

常用过滤器

  • filter() 将过滤器添加到原查询,返回一个新查询
  • filter_by() 把等值过滤器加到原查询上,返回一个新查询
  • limit() 使用指定的值限制原查询返回的结果数量,返回一个新查询
  • offset() 偏移查询返回的结果,返回一个新查询
  • order_by() 根据指定条件对远程讯结果进行排序,返回一个新查询
  • group_by() 根据指定条件对元查询结果进行分组,返回一个新查询

指定过滤器后,通过调用all()执行查询。

当然也有其他触发执行方法:

  • all() 以列表形式返回查询的所有结果
  • first() 返回查询的第一个结果,如果没有则返回None
  • first_or_404() 返回查询的第一个结果,如果没有就终止请求,返回404错误响应
  • get() 返回指定主键对应的行,没有则返回None
  • get_or_404()
  • count() 返回查询结果的数量
  • paginate() 返回一个Pagniate对象,包含指定范围内的结果

视图函数中操作数据库

语法与上面在终端的用法相同。

集成Python shell

每次启动shell会话需要导入数据库实例和模型,为了避免重复,做些配置即可。

from flask_script import Shell
def make_shell_context():
    return dict(app=app, db=db, User=User, Role=Role)
manager.add_command("shell",Shell(make_context=make_shell_context))

用Flask-Migrate实现数据库迁移

用到再详谈。

你可能感兴趣的:(高性能Python编程指南)