快速上手Flask(三) 在 Flask应用中使用Flask-SQLAlchemy

常见情况下对于只有一个 Flask 应用,所有您需要做的事情就是创建 Flask 应用,选择加载配置接着创建 SQLAlchemy 对象时候把 Flask 应用传递给它作为参数。

SQLAlchemy

官网:https://www.sqlalchemy.org/

参考本人 文章:python常用库之数据库orm框架之SQLAlchemy

什么是Flask-SQLAlchemy

官方文档:
中文:http://www.pythondoc.com/flask-sqlalchemy/index.html
[推荐]英文:https://flask-sqlalchemy.palletsprojects.com/en/3.1.x/

Flask-SQLAlchemy是一个Flask扩展,用于在Flask应用程序中简化与SQL数据库的交互。它提供了一个集成的ORM(对象关系映射)工具,使得在Flask应用程序中进行数据库操作更加方便和高效。

Flask-SQLAlchemy 和 SQLAlchemy的区别?

Flask-SQLAlchemy 是基于 SQLAlchemy 的 Flask 扩展,它提供了在 Flask 应用中更方便地使用 SQLAlchemy 的功能和特性。

  • 集成度:Flask-SQLAlchemy 是针对 Flask 框架的封装,提供了与 Flask 应用无缝集成的功能。它简化了在 Flask 应用中使用 SQLAlchemy 的配置和使用过程,提供了更简洁的接口和功能。

  • 配置:Flask-SQLAlchemy 提供了在 Flask 应用中配置 SQLAlchemy 的方式,可以直接在 Flask 配置中进行数据库相关的配置。而 SQLAlchemy 需要单独进行配置,通常使用一个独立的配置文件或模块。

  • 上下文管理:Flask-SQLAlchemy 自动处理了 SQLAlchemy 的上下文管理,确保在每个请求中使用正确的数据库会话。它与 Flask 的应用上下文和请求上下文无缝集成,提供了更方便的数据库操作方式。

  • 扩展功能:Flask-SQLAlchemy 提供了一些额外的功能和特性,如自动提交和回滚事务、自动创建数据库表、数据库迁移等。它还与 Flask-WTF 和 Flask-Admin 等其他 Flask 扩展集成得更紧密,提供了更丰富的功能和集成选项。

您仅需要知道与普通的 SQLAlchemy 不同之处:

  1. SQLAlchemy 允许您访问下面的东西:
    • sqlalchemy 和 sqlalchemy.orm 下所有的函数和类
    • 一个叫做 session 的预配置范围的会话(session)
    • metadata 属性
    • engine 属性
    • SQLAlchemy.create_all() 和 SQLAlchemy.drop_all(),根据模型用来创建以及删除表格的方法
    • 一个 Model 基类,即是一个已配置的声明(declarative)的基础(base)
  2. Model 声明基类行为类似一个常规的 Python 类,不过有个 query 属性,可以用来查询模型 (Model 和 BaseQuery)
  3. 您必须提交会话,但是没有必要在每个请求后删除它(session),Flask-SQLAlchemy 会帮您完成删除操作

Flask-SQLAlchemy基本使用

安装:

pip install -U Flask-SQLAlchemy

快速入门

快速入门
参考URL: http://www.pythondoc.com/flask-sqlalchemy/quickstart.html

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

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:tmp/test.db'
db = SQLAlchemy(app)


class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True)
    email = db.Column(db.String(120), unique=True)

    def __init__(self, username, email):
        self.username = username
        self.email = email

    def __repr__(self):
        return '<User %r>' % self.username

在 Flask 中使用 SQLAlchemy 进行数据库操作时,你应该在全局范围内创建一个 db 对象。

from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import create_engine
from sqlalchemy.pool import QueuePool

db = SQLAlchemy()

# 数据库连接配置
DATABASE_URI = 'postgresql://username:password@localhost:5432/database_name'
DATABASE_TRACK_MODIFICATIONS = False

# SQLAlchemy配置
SQLALCHEMY_DATABASE_URI = DATABASE_URI
SQLALCHEMY_TRACK_MODIFICATIONS = DATABASE_TRACK_MODIFICATIONS
SQLALCHEMY_ENGINE_OPTIONS = {
    'poolclass': QueuePool,
    'pool_size': 10,
    'max_overflow': 5,
    'pool_pre_ping': True
}

# 创建数据库引擎
engine = create_engine(DATABASE_URI, poolclass=QueuePool, pool_size=10, max_overflow=5, pool_pre_ping=True)

SQLALCHEMY_ENGINE_OPTIONS:这是SQLAlchemy的引擎配置选项,用于配置连接池的相关参数,例如pool_size和max_overflow。
engine:这是使用create_engine函数创建的数据库引擎对象,可以在需要直接使用底层引擎的情况下使用。

在你的代码中,你已经正确地创建了一个 db 对象,并将其与 Flask 应用程序绑定。这样做可以确保在整个应用程序中使用相同的数据库实例。

from flask import Flask
from api import create_app
from sqlalchemy_db import db, SQLALCHEMY_DATABASE_URI, SQLALCHEMY_TRACK_MODIFICATIONS, SQLALCHEMY_ENGINE_OPTIONS

app = create_app(os.getenv('FLASK_CONFIG') or 'default')

# 配置数据库连接URI和选项
app.config['SQLALCHEMY_DATABASE_URI'] = SQLALCHEMY_DATABASE_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = SQLALCHEMY_TRACK_MODIFICATIONS
app.config['SQLALCHEMY_ENGINE_OPTIONS'] = SQLALCHEMY_ENGINE_OPTIONS

# 将db对象与Flask应用程序关联
db.init_app(app)

在执行原生SQL语句时,使用engine对象。

以下是一个示例代码,演示了如何使用engine对象执行原生SQL查询:

from sqlalchemy_db import engine

def execute_native_sql(query):
    with engine.connect() as connection:
        result = connection.execute(query)
        for row in result:
            print(row)

# 示例查询
query = "SELECT * FROM users"
execute_native_sql(query)

在上面的代码中,我们创建了一个execute_native_sql函数,它使用engine对象执行原生SQL查询并打印结果。

请注意,在使用engine对象时,你需要根据具体的情况选择适当的上下文管理器(with语句)来保证连接的正确关闭。

如果你只是想使用SQLAlchemy的ORM功能(例如定义模型类、执行查询等),则可以直接使用db对象,而不需要直接使用engine对象。

创建模型

在使用SQLAlchemy之前,你需要先定义数据库模型类。模型类代表了数据库中的表结构,并提供了与表相关联的字段和方法。

from sqlalchemy_db import db

class User(db.Model):
    __tablename__ = 'users'
    
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(50), unique=True, nullable=False)
    email = db.Column(db.String(100), unique=True, nullable=False)
    
    def __repr__(self):
        return f'<User(id={self.id}, username={self.username}, email={self.email})>'

在上面的示例中,我们定义了一个名为User的模型类,它对应了数据库中的users表。User类继承了db.Model,这是SQLAlchemy提供的基类。

from sqlalchemy_db import db
from models import User

# 创建数据库表
db.create_all()

# 创建一个新用户
user = User(username='john', email='john@example.com')
db.session.add(user)
db.session.commit()

# 查询所有用户
users = User.query.all()
for user in users:
    print(user)

# 查询特定用户
user = User.query.filter_by(username='john').first()
print(user)

# 更新用户信息
user.email = 'newemail@example.com'
db.session.commit()

# 删除用户
db.session.delete(user)
db.session.commit()

我们使用db.session来进行数据库操作,例如添加、查询、更新和删除用户记录。

flask模型对象如何json序列化输出

[推荐]Flask 学习-36.Flask-RESTful 序列化输出对象
参考URL:https://www.cnblogs.com/yoyoketang/p/16648730.html

通过flask-SQLAlchemy这一ORM工具所构建的数据库表模型,通过其语句所取出的数据通常是object类型的,这一类型并不能直接在方法中return返回一个JSON格式,因此需要先对从数据库中取出的数据进行序列化,然后再return给前端。

在网络上找到的三种序列化方法如下:

在模型定义的时候给序列化的方法
继承改写 flask 里面的 JSONEncoder类以及default方法
使用Marshmallow

装饰器marshal_with实际上是获取您的数据对象并应用字段过滤。编组可以处理单个对象、字典或对象列表。

https://www.cnblogs.com/yoyoketang/p/16648730.html

使用Flask-RESTful 提供的 fields 模块序列化输出需要的字段

from flask_restful import Resource, fields, marshal_with

user_fields = {
‘id’: fields.Integer,
‘username’: fields.String,
‘is_active’: fields.Boolean
}

class UserInfo(Resource):

@marshal_with(user_fields)
def get(self):
    user = Users.query.get(1)
    print(f'查询到的数据:{user}')
    return user

数据库的增删改查

Flask和SQLAlchemy的模型操作:增删改查方法详解
参考URL: https://www.51cto.com/article/757138.html

查询模型
在Flask和SQLAlchemy中,我们可以使用以下方法来查询模型:

查询所有模型:

users = User.query.all()

这将返回所有的用户模型对象。

查询单个模型:

user = User.query.filter_by(username='john').first()

这将返回一个用户名为’john’的用户模型对象。

使用复杂查询:

users = User.query.filter(User.email.endswith('@example.com')).all()

这将返回所有电子邮件以’@example.com’结尾的用户模型对象。

修改模型
在Flask和SQLAlchemy中,我们可以使用以下方法来修改模型:

修改单个属性:

user = User.query.filter_by(username='john').first()
user.email = 'newemail@example.com'
db.session.commit()

修改多个属性:

user = User.query.filter_by(username='john').first()
user.email = 'newemail@example.com'
user.password = 'newpassword'
db.session.commit()

这将修改用户名为’john’的用户的电子邮件和密码,并将更改保存到数据库。

删除模型
在Flask和SQLAlchemy中,我们可以使用以下方法来删除模型:

删除单个模型:

user = User.query.filter_by(username='john').first()
db.session.delete(user)
db.session.commit()

这将删除用户名为’john’的用户模型对象,并将更改保存到数据库。

删除多个模型:

users = User.query.filter_by(email='oldemail@example.com').all()
for user in users:
    db.session.delete(user)
db.session.commit()

完整的代码示例如下:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///mydatabase.db'
db = SQLAlchemy(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    password = db.Column(db.String(120), nullable=False)

    def __repr__(self):
        return '<User %r>' % self.username

# create database tables
db.create_all()

# add a new user to the database
user = User(username='john', email='john@example.com', password='password')
db.session.add(user)
db.session.commit()

# query all users
users = User.query.all()
print(users)

# query a single user
user = User.query.filter_by(username='john').first()
print(user)

# modify a user's email
user = User.query.filter_by(username='john').first()
user.email = 'newemail@example.com'
user.password = 'newpassword'
db.session.commit()

# delete a user
user = User.query.filter_by(username='john').first()
db.session.delete(user)
db.session.commit()

首先定义了一个User模型类,并使用db.create_all()方法创建了数据库表格。接着,我们添加了一个新用户到数据库中,并使用User.query.all()和User.query.filter_by()方法查询了用户。然后,我们修改了用户的电子邮件和密码,并使用db.session.commit()方法将更改保存到数据库。最后,我们使用db.session.delete()方法删除了用户,并使用db.session.commit()方法将更改保存到数据库。

工作常用总结

在 SQLAlchemy 中,怎么判断删除是否成功?

官方文档:https://docs.sqlalchemy.org/en/14/orm/query.html#sqlalchemy.orm.Query.delete

在 SQLAlchemy 中,可以使用 execute() 方法执行 DELETE 语句,delete() 方法返回的是一个整数,表示被删除的记录数。

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
 
# 创建引擎和Session
engine = create_engine('sqlite:///test.db')
session = sessionmaker(bind=engine)()
 
try:
    # 定义模型类(这里以User为例)
    class User(Base):
        __tablename__ = 'users'
        
        id = Column(Integer, primary_key=True)
        name = Column(String)
    
    # 查询所有名字为"John"的用户
    users = session.query(User).filter(User.name == "John").all()
    
    if len(users) > 0:
        # 删除第一个找到的用户
        deleted_count = session.delete(users[0])
        print("已删除{}个用户".format(deleted_count))
        session.commit()
    else:
        print("未找到任何符合条件的用户")
except Exception as e:
    print("删除失败:", str(e))
finally:
    session.close()
01-22 08:50