Flask 学习笔记 7-- 数据库基本操作

2018/05/12 Flask

一. 增删改操作

1. 基本概念

  • 在 Flask-SQLAlchemy 中,插入、修改、删除操作,均由数据库会话管理。
    • 会话用 db.sessioni 表示。在准备把数据写入数据库前,要先将数据添加到会话中然后调用 commit() 方法提交会话。
  • 在 Flask-SQLAlchemy 中,查询操作是返回表中所有数据。
    • 最基本的查询时返回表中所有数据,可以通过过滤器进行更精确的数据库查询。
db.session.add(role)       # 添加到数据库的 session 中
db.session.add_all([user1, user2]) # 添加多个信息到 session 中
db.session.commit()        # 提交数据库的修改(包括增 / 删 / 改)
db.session.rollback()      # 数据库的回滚操作
db.session.delete(user)    # 删除数据库(需要跟上 commit)

2. 示例

2.1 在视图函数中定义模型类

Flask_SQLAlchemy_demo.py 如下:

# -*- coding:utf-8 -*-
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

# 配置数据库跟踪地址
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:qiu66666@127.0.0.1:3306/flask_sql_demo'
# 跟踪数据库的修改 --> 不建议开启 未来的版本中会移除
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

'''
两张表
角色(管理元 / 普通用户)
用户(角色 ID)
'''


# 数据库的模型,需要继承 db.Model
class Role(db.Model):
    # 定义表名
    __tablename__ = 'roles'

    # 定义字段
    # db.Column 表示一个字段
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(16), unique=True)

    # 在一的一方,写关联
    # users = db.relationship('User'): 表示和 User 模型发生了关联,增加了一个 users 属性
    users = db.relationship('User', backref='role')

    # repr() 方法显示一个可读字符串
    def __repr__(self):
        return '<Role: %s %s>' % (self.name, self.id)


class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(16), unique=True)
    email = db.Column(db.String(32), unique=True)
    password = db.Column(db.String(32))
    # db.ForeignKey('roles.id') 表示时外键,表名. id
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
    # User 希望有 role 属性,但是这个属性的定义,需要在另一个模型中定义

    def __repr__(self):
        return '<User: %s %s %s %s>' % (self.name, self.id, self.email, self.password)


@app.route('/')
def hello_world():
    return 'Hello World!'


if __name__ == '__main__':
    # 删除表
    db.drop_all()

    # 创建表
    db.create_all()

    app.run(debug=True)

2.2 在终端进行增删改操作:

>>> from Flask_SQLAlchemy_demo import *

# 添加一条 Role 数据
>>> role = Role(name='admin')
>>> db.session.add(role)
>>> db.session.commit()

# 添加一条 User 数据,数据有误可以使用回滚,将 add 的对象从 session 移除
>>> user = User(name='qinbin')
>>> db.session.add(user)
>>> db.sessioon.rollback()
>>> user.role_id = 1
>>> db.session.add(user)
>>> db.session.commit()

# 修改数据
>>> user.name = 'qiuling'
>>> db.session.commit()

# 删除数据
>>> db.session.delete(user)
>>> db.session.commit()

3. 模型之间的关联

3.1 一对多

class Role(db.Model):
    ...
    # 关键代码
    user = db.relationship('User', backref='role')
    ...


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

  • 其中 relationship 描述了 Role 和 User 的关系。在此文中,第一个参数为对应参照的类 “User”
  • 第二个参数 backref 为类 User 申明新属性的方法
# 1. 添加一个角色和两个用户

In [1]: from Flask_SQLAlchemy_demo import *

In [2]: role = Role(name='admin')

In [3]: db.session.add(role)

In [4]: db.session.commit()

In [5]: user1 = User(name='zs', role_id=role.id)

In [6]: user2 = User(name='ls', role_id=role.id)

In [7]: db.session.add_all([user1, user2])

In [8]: db.session.commit()

# 2. 实现关系引用查询

In [9]: role.users
Out[9]: [<User: zs 1 None None>, <User: ls 2 None None>]

In [10]: user1.role
Out[10]: <Role: admin 1>

In [11]: user2.role
Out[11]: <Role: admin 1>

In [12]: user2.role.name
Out[12]: u'admin'

二. 查询操作

1. 基本概念

1.1 常用的 SQLAlchemy 查询过滤器

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

1.2 常用的 SQLAlchemy 查询执行器

方法 说明
all() 以列表形式返回查询的所有结果
first() 返回查询的第一个结果,如果未查到,返回 None
first_or_404() 返回查询的第一个结果,如果未查到,返回 404
get() 返回指定主键对应的行,如不存在,返回 NOne
get_or_404() 返回指定主键对应的行,如不存在,返回 404
count() 返回查询结果的数量
paginate() 返回一个 Paginate 对象,它包含指定范围内的结果

2. 示例

2.1 插入角色数据

ro1 = Role(name='admin')
db.session.add(rol)
db.session.commit()
# 再次插入一条数据
ro2 = Role(name='user')
db.session.add(ro2)
db.session.commit()

2.2 一次插入多条数据

us1 = User(name='wang', email='wang@163.com', password='123456', role_id=ro1.id)
us2 = User(name='zhang', email='zhang@189.com', password='20153', role_id=ro2.id)
us3 = User(name='chen', email='chen@126.com', password='343224', role_id=ro2.id)
us4 = User(name='su', email='su@163.com', password='434323', role_id=ro1.id)
us5 = User(name='zhou', email='zhou@qinbin.com', password='666666', role_id=ro2.id)
us6 = User(name='wu', email='wu@gmail.com', password='473735', role_id=ro2.id)
us7 = User(name='qian', email='qian@qq.com', password='544454', role_id=ro1.id)
us8 = User(name='liu', email='liu@163.com', password='765756', role_id=ro1.id)
us9 = User(name='sun', email='sun@163.com', password='090909', role_id=ro1.id)
us10 = User(name='qin', email='qin@qq.com', password='888888', role_id=ro2.id)
us11 = User(name='lu', email='lu@163.com', password='972668', role_id=ro2.id)
us12 = User(name='tang', email='tang@qq.com', password='096536', role_id=ro2.id)
db.session.add_all([us1, us2, us3, us4, us5, us6, us7, us8, us9, us10, us11, us12])
db.session.commit()

2.3 查询练习如下

# 1. 查询所有用户数据
# all() 返回查询到的所有对象
User.query.all()

# 2. 查询有多少个用户
User.query.count()

# 3. 查询第一个用户
User.query.first()

# 4. 查询 id 为 4 的用户【3 种方式】
# filter_by 直接用属性名,比较用 =,filter 用类名. 属性名,比较用 ==
# filter_by 用于查询简单的列名,不支持比较运算符
# filter 比 filter_by 的功能更加强大,支持比较运算符,支持 or_、in_等语法
User.query.get(4)
User.query.filter_by(id=4).first()  # 属性 =
User.query.filter(User.id==4).first()    # 对象名. 属性 ==

代码如下:

# -*- coding:utf-8 -*-
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

# 配置数据库跟踪地址
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:qiu66666@127.0.0.1:3306/flask_sql_demo'
# 跟踪数据库的修改 --> 不建议开启 未来的版本中会移除
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

'''
两张表
角色(管理元 / 普通用户)
用户(角色 ID)
'''


# 数据库的模型,需要继承 db.Model
class Role(db.Model):
    # 定义表名
    __tablename__ = 'roles'

    # 定义字段
    # db.Column 表示一个字段
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(16), unique=True)

    # 在一的一方,写关联
    # users = db.relationship('User'): 表示和 User 模型发生了关联,增加了一个 users 属性
    users = db.relationship('User', backref='role')

    # repr() 方法显示一个可读字符串
    def __repr__(self):
        return '<Role: %s %s>' % (self.name, self.id)


class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(16), unique=True)
    email = db.Column(db.String(32), unique=True)
    password = db.Column(db.String(32))
    # db.ForeignKey('roles.id') 表示时外键,表名. id
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

    # User 希望有 role 属性,但是这个属性的定义,需要在另一个模型中定义

    def __repr__(self):
        return '<User: %s %s %s %s>' % (self.name, self.id, self.email, self.password)


@app.route('/')
def hello_world():
    return 'Hello World!'


if __name__ == '__main__':
    # 删除表
    db.drop_all()

    # 创建表
    db.create_all()

    ro1 = Role(name='admin')
    db.session.add(ro1)
    db.session.commit()
    # 再次插入一条数据
    ro2 = Role(name='user')
    db.session.add(ro2)
    db.session.commit()

    us1 = User(name='wang', email='wang@163.com', password='123456', role_id=ro1.id)
    us2 = User(name='zhang', email='zhang@189.com', password='20153', role_id=ro2.id)
    us3 = User(name='chen', email='chen@126.com', password='343224', role_id=ro2.id)
    us4 = User(name='su', email='su@163.com', password='434323', role_id=ro1.id)
    us5 = User(name='zhou', email='zhou@qinbin.com', password='666666', role_id=ro2.id)
    us6 = User(name='wu', email='wu@gmail.com', password='473735', role_id=ro2.id)
    us7 = User(name='qian', email='qian@qq.com', password='544454', role_id=ro1.id)
    us8 = User(name='liu', email='liu@163.com', password='765756', role_id=ro1.id)
    us9 = User(name='sun', email='sun@163.com', password='090909', role_id=ro1.id)
    us10 = User(name='qin', email='qin@qq.com', password='888888', role_id=ro2.id)
    us11 = User(name='lu', email='lu@163.com', password='972668', role_id=ro2.id)
    us12 = User(name='tang', email='tang@qq.com', password='096536', role_id=ro2.id)
    db.session.add_all([us1, us2, us3, us4, us5, us6, us7, us8, us9, us10, us11, us12])
    db.session.commit()

    app.run(debug=True)

操作过程如下:

In [1]: from Flask_SQLAlchemy_demo import *

In [2]: User.query.all()
Out[2]:
[<User: wang 1 wang@163.com 123456>,
 <User: zhang 2 zhang@189.com 20153>,
 <User: chen 3 chen@126.com 343224>,
 <User: su 4 su@163.com 434323>,
 <User: zhou 5 zhou@qinbin.com 666666>,
 <User: wu 6 wu@gmail.com 473735>,
 <User: qian 7 qian@qq.com 544454>,
 <User: liu 8 liu@163.com 765756>,
 <User: sun 9 sun@163.com 090909>,
 <User: qin 10 qin@qq.com 888888>,
 <User: lu 11 lu@163.com 972668>,
 <User: tang 12 tang@qq.com 096536>]

In [3]: User.query.count()
Out[3]: 12L

In [4]: User.query.first()
Out[4]: <User: wang 1 wang@163.com 123456>

In [5]: User.query.get(4)
Out[5]: <User: su 4 su@163.com 434323>

In [6]: User.query.filter_by(id=4).first()
Out[6]: <User: su 4 su@163.com 434323>

In [7]: User.query.filter(User.id==4).first()
Out[7]: <User: su 4 su@163.com 434323>

# filter_by: 属性 =
# filter: 对象. 属性 ==
# filter 功能更强大,可以实现更多的一些查询,支持比较运算符

flask_sql_demo 数据库中的数据

mysql> select * from roles;
+----+-------+
| id | name  |
+----+-------+
|  1 | admin |
|  2 | user  |
+----+-------+
2 rows in set (0.00 sec)

mysql> select * from users;
+----+-------+-----------------+----------+---------+
| id | name  | email           | password | role_id |
+----+-------+-----------------+----------+---------+
|  1 | wang  | wang@163.com    | 123456   |       1 |
|  2 | zhang | zhang@189.com   | 20153    |       2 |
|  3 | chen  | chen@126.com    | 343224   |       2 |
|  4 | su    | su@163.com      | 434323   |       1 |
|  5 | zhou  | zhou@qinbin.com | 666666   |       2 |
|  6 | wu    | wu@gmail.com    | 473735   |       2 |
|  7 | qian  | qian@qq.com     | 544454   |       1 |
|  8 | liu   | liu@163.com     | 765756   |       1 |
|  9 | sun   | sun@163.com     | 090909   |       1 |
| 10 | qin   | qin@qq.com      | 888888   |       2 |
| 11 | lu    | lu@163.com      | 972668   |       2 |
| 12 | tang  | tang@qq.com     | 096536   |       2 |
+----+-------+-----------------+----------+---------+
12 rows in set (0.00 sec)

Search

    Table of Contents