Flask-SQLAlchemy 对数据库的增查改删

2021-02-26 15:34:26 浏览数 (1)

使用 Flask-SQLAlchemy 连接数据库,可以通过 Python 对象来操作数据库。

Flask-SQLAlchemy 连接数据库参考: Flask-SQLALchemy 连接数据库

连接数据库后,接下来继续介绍对数据库的基本操作。

一、数据库准备和创建表

1. 连接数据库

使用 Mysql 数据库,使用我之前创建的 admin 用户连接。

代码语言:javascript复制
mysql -u admin -p

如果没有创建,就先登录 root 用户创建用户,也可以直接用 root 用户连接。用哪个用户连接无所谓,只要能正常连接就可以了。

代码语言:javascript复制
grant all privileges on *.* to 'admin'@'localhost' identified by 'Mysql!123';

2. 创建一个数据库

使用我之前创建好的数据 MyDB_one ,如果没有就创建。用哪个数据库是自定义的,只要有一个数据库供使用即可。

代码语言:javascript复制
create database MyDB_one charset utf8;

3. 使用 Flask-SQLAlchemy 创建数据表

创建一个 flask_alchemy_tb.py 文件,编写创建数据表的代码。

代码语言:javascript复制
from flask import Flask
from flask_sqlalchemy import SQLAlchemy


app = Flask(__name__)


app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://admin:Mysql!123@127.0.0.1:3306/MyDB_one'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)


class Phone(db.Model):
    __tablename__ = 'Phone_tb'
    pid = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32))
    person = db.relationship('Person', backref='person')

    def __repr__(self):
        return 'Phone_name: {}'.format(self.name)


class Person(db.Model):
    __tablename__ = 'Person_tb'
    mid = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    age = db.Column(db.Integer)
    phone = db.Column(db.Integer, db.ForeignKey('Phone_tb.pid'))

    def __repr__(self):
        return 'Person_name: {}'.format(self.name)


# db.drop_all()
db.create_all()


if __name__ == '__main__':

    app.run(debug=True)

代码中连接了使用的数据库,创建了两个数据库模型类,使用 db 对象的 create_all() 方法来创建两张数据表,如果需要删除,可以使用 drop_all() 方法来删除数据表。注意删除操作要小心,删除之后表中的数据都没有了。

运行代码,就会在 MyDB_one 中创建两张数据表 Person_tb 和 Phone_tb 。

查看两张表中的字段,与代码中的字段一致。

二、常用的SQLAlchemy字段类型

创建数据表时,每个字段的数据类型是不一样的,在 SQLAlchemy 中通过 SQLAlchemy 对象 db 的字段类型来指定。

常用的字段类型有以下这些:

1. Integer: 整数,一般是32位

2. SmallInteger: 取值范围小的整数,一般是16位

3. BigInteger: 不限制长度的整数

4. Float: 浮点数

5. Numeric: 普通整数,一般是32位

6. String: 变长字符串

7. Text: 变长字符串,对较长或不限长度的字符串做了优化

8. Unicode: 变长Unicode字符串

9. Boolean: 布尔值

10. Date: 时间

11. Time: 日期和时间

三、在数据表中添加、查询、修改、删除数据

在 Flask-SQLAlchemy 中,进行添加、查询、修改、删除操作,都是由 SQLAlchemy 对象的数据库会话管理来实现的。

db 对象的数据库会话管理用 db.session 表示。

继续在上面的 .py 文件中添加代码,已经创建好了数据表,所以把创建数据表的代码注释掉。

代码语言:javascript复制
# db.create_all()

app 是 Flask 的后台运行对象,创建数据库并不依赖 app 的运行,只需要使用 SQLAlchemy 对象 db 就可以了,所以把 app.run() 也注释掉。

代码语言:javascript复制
# app.run(debug=True)

1. 在数据表中添加一条数据

如在 Phone_tb 中添加一条数据,先创建一个数据库模型类 Phone 的对象 phone_one,然后使用 db.session 的 add() 方法将 phone_one 添加到数据库会话中,最后执行 db.session.commit() 提交数据库会话。

代码语言:javascript复制
if __name__ == '__main__':

    phone_one = Phone(name='IPhone')
    db.session.add(phone_one)
    db.session.commit()

创建对象 phone_one 对象时通过键值对的方式指定每个字段的值,与数据库模型类中定义的字段相对应,主键可以不指定。

运行之后,会在 Phone_tb 表中添加一条 name 为 IPhone 的数据。

2. 一次在数据表中添加多条数据

可以先创建好多个数据库模型类的对象,然后使用 db.session 的 add_all() 方法将所有模型类对象以列表的方式添加到数据库会话中,最后执行 db.session.commit() 提交数据库会话。

代码语言:javascript复制
    phone_two = Phone(name='Mi')
    phone_three = Phone(name='NOKIA')
    db.session.add_all([phone_two, phone_three])
    db.session.commit()

注释掉添加一条数的代码,然后执行上面的代码,会继续在 Phone_tb 表中添加两条数据。

如果数据表中有唯一字段时,唯一字段的值不能重复,如 Person 模型类中的 name 字段,否则会报错。

如果数据表中有关系字段时,关系字段的数据必须存在,如 Person 模型类中的 phone 字段关联到 Phone 模型类中的 pid ,所以 Phone_tb 中要先有对应 pid 的数据,否则 Person_tb 中的 phone 字段为空或报错。

代码语言:javascript复制
    per_one = Person(name='You', age=18, phone=1)
    per_two = Person(name='Me', age=81, phone=2)
    db.session.add_all([per_one, per_two])
    db.session.commit()

注释掉在 Phone_tb 中添加数据的代码,在 Person_tb 中也添加两条数据。

3. 查询数据表中的数据

在 Flask-SQLAlchemy 中,查询操作是通过数据库模型类对象的 query 对象来完成的。

最基本的查询是调用 query 对象的 all() 方法返回数据表中的所有数据,也可以通过 query 对象的过滤器进行更精确的数据库查询,过滤查询后面再研究。

代码语言:javascript复制
    all_person = Person.query.all()
    print(all_person)

运行上面的查询代码,结果如下:

代码语言:javascript复制
[Person_name: You, Person_name: Me]

这里只显示查询结果的 name 字段,是因为在定义模型类对象的时候,重写了 db.Model 的 __repr__ 方法,显示结果按 __repr__ 方法中的定义来显示。

4. 修改数据表中的数据

在 Person_tb 中,对第二条数据进行修改。

代码语言:javascript复制
    me = Person.query.get(2)
    print(me.phone)
    me.phone = 3
    db.session.commit()
    me = Person.query.get(2)
    print(me.phone)

先将数据查询出来,然后修改数据对象的值,再通过 db.session 数据会话将修改结果提交到数据表中,重新从数据表中查询结果,查询结果已经改变了。

运行上面的代码,第二条数据 Me 的 phone 从 2 Mi 修改为 3 NOKIA ,运行结果如下:

代码语言:javascript复制
2
...
3

再到数据表中进行查询,第二条数据确实发生了变化,修改成功。

5. 删除数据表中的数据

现在将两张数据表中的所有数据都删除。

代码语言:javascript复制
    all_person = Person.query.all()
    all_phone = Phone.query.all()
    for phone in all_phone:
        db.session.delete(phone)
        db.session.commit()
    for person in all_person:
        db.session.delete(person)
        db.session.commit()

可以看到,不管是修改还是删除,都需要先从数据表中将数据查询出来。

查询出数据后,使用 db.session 数据会话的 delete() 方法来删除数据,query 对象的 all() 方法查询出来的数据是一个查询集,是可迭代的,所以可以遍历来删除。

db.session 并没有 delete_all() 的方法,如果有这个方法也是一个危险的方法,如果需要,可以自己把上面的代码封装一下,用作删除所有数据的方法。

运行上面的代码后,再到数据表中查询数据,空空如也。

在本文的所有操作中,都是通过调用各种对象的各种方法来实现的,这就是面向对象编程的魅力吧。

0 人点赞