Flask--数据库操作

来源:互联网 发布:金十数据官网财经报告 编辑:程序博客网 时间:2024/06/04 21:21

Flask 数据库

1. 使用Flask-SQLAlchemy管理数据库

Flask使用Flask-SQLAlchemy管理数据库,安装方式:

$ pip install flask-sqlalchemy

在 Flask-SQLAlchemy 中,数据库使用 URL 指定:

MySQL mysql://username:password@hostname/databasePostgres postgresql://username:password@hostname/databaseSQLiteUnixsqlite:////absolute/path/to/databaseSQLiteWindowssqlite:///c:/absolute/path/to/database

程序使用的数据库 URL 必须保存到 Flask 配置对象的 SQLALCHEMY_DATABASE_URI 键中。
配置对象中还有一个很有用的选项, 即 SQLALCHEMY_COMMIT_ON_TEARDOWN 键,将其设为 True时,每次请求结束后都会自动提交数据库中的变动。

初始化以及配置一个简单的SQLite数据库:

from osfrom flask import Flaskfrom flask.ext.sqlalchemy import SQLAlchemybasedir = os.path.abspath(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'] = Truedb = SQLAlchemy(app)

2. 定义模型

在 ORM 中,模型一般是一个 Python 类,类中的属性对应数据库表中的列。
下面定义两个表对应的Python类。

class Role(db.Model):    __tablename__ = 'roles'    id = db.Column(db.Integer, primary_key=True)    name = db.Column(db.String(64), unique=True)    users = db.relationship('User', backref='role')    def __repr__(self):        return '<Role %r>' % self.nameclass User(db.Model):    __tablename__ = 'users'    id = db.Column(db.Integer, primary_key=True)    username=db.Column(db.String(64), unique=True, index=True)    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))    def __repr__(self):        return '<User %r>' % self.username

类变量 __tablename__ 定义在数据库中使用的表名。如果没有定义 __tablename__Flask-SQLAlchemy会使用一个默认名字,但默认的表名没有遵守使用复数形式进行命名的约定,所以最好由我们自己来指定表名。其余的类变量都是该模型的属性,被定义为 db.Column类的实例。

下图显示了最常用的SQLAlchemy列的类型:
这里写图片描述

下图显示了最常用的SQLAlchemy列选项:
这里写图片描述

Flask-SQLAlchemy 要求每个模型都要定义主键,这一列经常命名为 id。

3. 定义模型的关系

上面的User类和Role类中,通过下面的代码定义了两个类的关系:

class Role(db.Model):    # ...    users = db.relationship('User', backref='role', lazy='dynamic')class User(db.Model):    # ...    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

之前定义了两个表的名字:usersroles

关系使用 users 表中的外键连接了两行。添加到 User 模型中的 role_id 列被定义为外键, 就是这个外键建立起了关系。传给 db.ForeignKey() 的参数 'roles.id' 表明,这列的值是 roles 表中行的 id值。

添加到 Role 模型中的 users 属性代表这个关系的面向对象视角。对于一个 Role 类的实例,其 users 属性将返回与角色相关联的用户组成的列表。db.relationship() 的第一个参数表明这个关系的另一端是哪个模型。

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

其中参数lazy的作用是:禁止自动查询,当在一个Role对象中调用users属性的时候,会自动执行query,返回所有的属于该Role对象的User对象,因此无法在此结果上附加更精确的查询过滤器。例如原来这样直接获取User对象users = user_role.users,增加lazy参数后这样获取:user_role.users.order_by(User.username).all(),增加了更精确的过滤器。

4. 数据配置

在该部分实现数据库的创建、初始化等工作,所以把这部分代码放在manage.py文件中:

#!/usr/bin/env python# -*- coding: utf-8 -*-from flask_script import Manager, Server, Shellfrom somepackage import app, dbfrom somepackage import User, Rolemanager = Manager(app)@manager.commanddef init_db():    """    Init the DB and Insert test data    """    # this db is a SQLAlchemy instance, must be imported.    # the create_all method is belonged to SQLAlchemy instance.    db.create_all()    admin_role = Role(id=1, name="Admin")    user_role = Role(id=2, name="User")    user_jhon = User(id=1, username="Jhon", role=admin_role)    user_david = User(id=2, username="david", role=user_role)    db.session.add_all([admin_role, user_role, user_jhon, user_david])    try:        db.session.commit()    except Exception, e:        db.session.rollback()        print eif __name__ == "__main__":    manager.run()

注意:其中的UserRole,以及db都要从合适的包或者模块中引入进来。

这样就能够创建并初始化数据库。下面看SQLAlchemy提供的过滤器和查询函数:
这里写图片描述
这里写图片描述

其中filterfilter_by的区别就是:filter_by之后的条件直接是字段=查询的值filter之后的条件是类名.字段=查询条件

5. 数据库操作

通过上面的配置就可以在视图函数中操作数据库了:

@app.route('/', methods=['GET', 'POST'])def index():    form = NameForm()    if form.validate_on_submit():        user = User.query.filter_by(username=form.name.data).first()         if user is None:            user = User(username = form.name.data)            db.session.add(user)            session['known'] = False        else:            session['known'] = True            session['name'] = form.name.data            form.name.data = ''            return redirect(url_for('index'))    return render_template('index.html',                            form = form,                             name = session.get('name'),                            known = session.get('known', False)
0 0