Flask--数据库操作

Flask 数据库

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

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

$ pip install flask-sqlalchemy

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

MySQL mysql://username:password@hostname/database
Postgres postgresql://username:password@hostname/database
SQLiteUnixsqlite:////absolute/path/to/database
SQLiteWindowssqlite:///c:/absolute/path/to/database

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

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

from os
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy

basedir = 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'] = True

db = 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 '' % 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)
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

    def __repr__(self):
        return '' % self.username

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

下图显示了最常用的SQLAlchemy列的类型:
Flask--数据库操作_第1张图片

下图显示了最常用的SQLAlchemy列选项:
Flask--数据库操作_第2张图片

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, Shell
from somepackage import app, db
from somepackage import User, Role

manager = Manager(app)

@manager.command
def 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 e

if __name__ == "__main__":
    manager.run()

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

这样就能够创建并初始化数据库。下面看SQLAlchemy提供的过滤器和查询函数:
Flask--数据库操作_第3张图片
Flask--数据库操作_第4张图片

其中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)

你可能感兴趣的:(Flask后端开发)