SQLAlchemy 在 Flask 应用中的使用和最佳实践

### SQLAlchemy 在 Flask 应用中的使用和最佳实践

  • [@[TOC](SQLAlchemy 在 Flask 应用中的使用和最佳实践)](#SQLAlchemy 在 Flask 应用中的使用和最佳实践 @[TOC](SQLAlchemy 在 Flask 应用中的使用和最佳实践) 模型的编写 SQLAlchemy 中建立关联 利用 SQLAlchemy 中的关联进行查询 实现示例 backref与back_populates? backref反向引用 back_populates后填充 层面的关系 数据库层面的关系 SQLAlchemy ORM 层面的关系 模型的导入)
  • [模型的编写](#SQLAlchemy 在 Flask 应用中的使用和最佳实践 @[TOC](SQLAlchemy 在 Flask 应用中的使用和最佳实践) 模型的编写 SQLAlchemy 中建立关联 利用 SQLAlchemy 中的关联进行查询 实现示例 backref与back_populates? backref反向引用 back_populates后填充 层面的关系 数据库层面的关系 SQLAlchemy ORM 层面的关系 模型的导入)
  • [**SQLAlchemy 中建立关联**](#SQLAlchemy 在 Flask 应用中的使用和最佳实践 @[TOC](SQLAlchemy 在 Flask 应用中的使用和最佳实践) 模型的编写 SQLAlchemy 中建立关联 利用 SQLAlchemy 中的关联进行查询 实现示例 backref与back_populates? backref反向引用 back_populates后填充 层面的关系 数据库层面的关系 SQLAlchemy ORM 层面的关系 模型的导入)
  • [**利用 SQLAlchemy 中的关联进行查询**](#SQLAlchemy 在 Flask 应用中的使用和最佳实践 @[TOC](SQLAlchemy 在 Flask 应用中的使用和最佳实践) 模型的编写 SQLAlchemy 中建立关联 利用 SQLAlchemy 中的关联进行查询 实现示例 backref与back_populates? backref反向引用 back_populates后填充 层面的关系 数据库层面的关系 SQLAlchemy ORM 层面的关系 模型的导入)
  • [**实现示例**](#SQLAlchemy 在 Flask 应用中的使用和最佳实践 @[TOC](SQLAlchemy 在 Flask 应用中的使用和最佳实践) 模型的编写 SQLAlchemy 中建立关联 利用 SQLAlchemy 中的关联进行查询 实现示例 backref与back_populates? backref反向引用 back_populates后填充 层面的关系 数据库层面的关系 SQLAlchemy ORM 层面的关系 模型的导入)
  • [backref与back_populates?](#SQLAlchemy 在 Flask 应用中的使用和最佳实践 @[TOC](SQLAlchemy 在 Flask 应用中的使用和最佳实践) 模型的编写 SQLAlchemy 中建立关联 利用 SQLAlchemy 中的关联进行查询 实现示例 backref与back_populates? backref反向引用 back_populates后填充 层面的关系 数据库层面的关系 SQLAlchemy ORM 层面的关系 模型的导入)
  • [**backref反向引用**](#SQLAlchemy 在 Flask 应用中的使用和最佳实践 @[TOC](SQLAlchemy 在 Flask 应用中的使用和最佳实践) 模型的编写 SQLAlchemy 中建立关联 利用 SQLAlchemy 中的关联进行查询 实现示例 backref与back_populates? backref反向引用 back_populates后填充 层面的关系 数据库层面的关系 SQLAlchemy ORM 层面的关系 模型的导入)
  • [**back_populates后填充**](#SQLAlchemy 在 Flask 应用中的使用和最佳实践 @[TOC](SQLAlchemy 在 Flask 应用中的使用和最佳实践) 模型的编写 SQLAlchemy 中建立关联 利用 SQLAlchemy 中的关联进行查询 实现示例 backref与back_populates? backref反向引用 back_populates后填充 层面的关系 数据库层面的关系 SQLAlchemy ORM 层面的关系 模型的导入)
  • [****层面的关系****](#SQLAlchemy 在 Flask 应用中的使用和最佳实践 @[TOC](SQLAlchemy 在 Flask 应用中的使用和最佳实践) 模型的编写 SQLAlchemy 中建立关联 利用 SQLAlchemy 中的关联进行查询 实现示例 backref与back_populates? backref反向引用 back_populates后填充 层面的关系 数据库层面的关系 SQLAlchemy ORM 层面的关系 模型的导入)
  • [**数据库层面的关系**](#SQLAlchemy 在 Flask 应用中的使用和最佳实践 @[TOC](SQLAlchemy 在 Flask 应用中的使用和最佳实践) 模型的编写 SQLAlchemy 中建立关联 利用 SQLAlchemy 中的关联进行查询 实现示例 backref与back_populates? backref反向引用 back_populates后填充 层面的关系 数据库层面的关系 SQLAlchemy ORM 层面的关系 模型的导入)
  • [**SQLAlchemy ORM 层面的关系**](#SQLAlchemy 在 Flask 应用中的使用和最佳实践 @[TOC](SQLAlchemy 在 Flask 应用中的使用和最佳实践) 模型的编写 SQLAlchemy 中建立关联 利用 SQLAlchemy 中的关联进行查询 实现示例 backref与back_populates? backref反向引用 back_populates后填充 层面的关系 数据库层面的关系 SQLAlchemy ORM 层面的关系 模型的导入)
  • [模型的导入](#SQLAlchemy 在 Flask 应用中的使用和最佳实践 @[TOC](SQLAlchemy 在 Flask 应用中的使用和最佳实践) 模型的编写 SQLAlchemy 中建立关联 利用 SQLAlchemy 中的关联进行查询 实现示例 backref与back_populates? backref反向引用 back_populates后填充 层面的关系 数据库层面的关系 SQLAlchemy ORM 层面的关系 模型的导入)

在构建 Python web 应用时,处理数据库是一个不可避免的任务。SQLAlchemy 作为一个强大的 SQL 工具包和对象关系映射(ORM)系统,为 Python 应用提供了高效处理数据库的能力。特别是在 Flask 这类框架中,SQLAlchemy 提供了一个直观的方式来定义数据模型和执行数据库操作。

模型的编写

在 SQLAlchemy 中,一个数据模型通常是通过定义一个类来创建的,这个类继承自 db.Model。模型类代表数据库表,类中的属性代表表中的列。例如:

jsx 复制代码
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

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)

在这个例子中,User 类代表一个用户表,其中包含 ID、用户名和电子邮件地址。

SQLAlchemy 中建立关联

SQLAlchemy 允许在模型间建立一对多、多对一或多对多的关系。例如,一个店铺拥有多个设备的一对多关系可以这样定义:

jsx 复制代码
class Store(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    devices = db.relationship('Device', backref='store')

class Device(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    store_id = db.Column(db.Integer, db.ForeignKey('store.id'))

利用 SQLAlchemy 中的关联进行查询

有了关联后,您可以轻松地在相关的模型之间进行数据查询。例如,要找到某个特定店铺的所有设备,您可以使用以下代码:

python 复制代码
store = Store.query.get(some_store_id)
devices = store.devices

实现示例

假设您的模型之间的关系如下所述:

python 复制代码
class GameRecord(db.Model):
    # ...
    device_id = db.Column(db.Integer, db.ForeignKey('device.id'))
    device = db.relationship('Device', backref='game_records')

class Device(db.Model):
    # ...
    store_id = db.Column(db.Integer, db.ForeignKey('store.id'))
    store = db.relationship('Store', backref='devices')

class Store(db.Model):
    # ...
    address = db.Column(db.String(200))

您可以这样获取游戏位置:

python 复制代码
game_record = GameRecord.query.get(some_id)
game_location = game_record.device.store.address

backref与back_populates?

在 SQLAlchemy 中,backrefback_populates 都是用来定义模型间双向关系的选项,但它们在使用上略有不同。理解这两个选项的区别有助于更好地组织和维护数据库模型的关系。

backref反向引用

  • backref 是一种在定义关系时快捷创建反向引用的方式。
  • 当您在一个模型(如 GameRecord )中定义了一个关系(比如到 User ),并使用了 backref ,SQLAlchemy 会自动在另一个模型(User)中创建一个反向关系。
  • 这意味着您无需在两个模型中都定义关系,SQLAlchemy 会为您处理这部分。

例如,在 GameRecord 模型中定义 user 关系时使用 backref

python 复制代码
class GameRecord(db.Model):
    # ...
    user = db.relationship('User', backref='game_records')

这将自动在 User 模型中创建一个 game_records 属性,可以通过它访问与该用户相关联的所有 GameRecord 实例。

back_populates后填充

  • back_populates 用于在两个模型间明确地创建双向关系。
  • backref 不同,使用 back_populates 需要在关联的两个模型中都明确地声明关系。
  • 这提供了更多的灵活性和清晰度,尤其是在复杂的关系中。

例如,设备(Device )和店铺(Store )的关系可以使用 back_populates 定义:

Device 模型中:

python 复制代码
class Device(db.Model):
    # ...
    store = db.relationship('Store', back_populates='devices')

Store 模型中:

python 复制代码
class Store(db.Model):
    # ...
    devices = db.relationship('Device', back_populates='store')

这样,Device 的每个实例都有一个 store 属性指向它所属的 Store ,同时每个 Store 实例都有一个 devices 属性指向所有属于该店铺的 Device 实例。

总而言之:

  • 使用 backref 更为简便,但可能在某些情况下不够明确。
  • 使用 back_populates 提供了更明确的关系定义,特别是在复杂的模型关系中。
  • 选择使用哪一个取决于具体的应用场景和个人编码风格。在大多数情况下,backref 足以满足需求,并且可以减少代码量。

层面的关系

在 SQLAlchemy 中使用 db.relationship 建立的一对多关系(如您示例中的 devices = db.relationship('Device', backref='store', lazy=True))在数据库层面是不直接体现的。这个关系存在于 SQLAlchemy ORM(对象关系映射)层面,用于在应用程序中方便地处理和查询数据库记录,但它不会直接映射为数据库表中的某个字段或结构。

数据库层面的关系

  • 在数据库层面,一对多关系通常是通过外键实现的。例如,在 Device 表中,会有一个字段(如 store_id ),作为外键指向 Store 表的主键。
  • 这种关系确保了数据的完整性和关联性,但它本身并不提供直接的查询机制。

SQLAlchemy ORM 层面的关系

  • db.relationship 是 SQLAlchemy 提供的高级抽象,允许您在两个模型类之间建立关联关系。
  • 这使得您可以用类似于操作普通 Python 对象的方式来处理数据库记录。例如,通过 store.devices 访问一个特定店铺的所有设备,或者通过 device.store 访问某个设备所属的店铺。
  • backref 参数在反向关系中添加了一个类似的便利属性,这样就可以从 Device 实例轻松访问其关联的 Store 实例。

总而言之:

  • 数据库层面的一对多关系是通过外键字段实现的。
  • SQLAlchemy ORM 层面的 db.relationship 为这种关系提供了一个更为直观和方便的操作接口,但它只存在于代码层面,不直接映射到数据库结构中。
  • 这种设计使得应用程序的后端开发更加简洁和直观,同时保持了数据库的完整性和效率。

模型的导入

如果模型创建的顺序不对,可能会报错,例如如下:

jsx 复制代码
sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'device.store_id' could not find table 'store' with which to generate a foreign key to target column 'id'

问题出现在创建数据库表时,SQLAlchemy 无法找到 device 表中 store_id 字段引用的 store 表。错误信息 sqlalchemy.exc.NoReferencedTableError 表明在尝试创建外键关系时,SQLAlchemy 无法找到被引用的表或列。

如果你确保你的表名都没有问题,你可能需要考虑你的模型定义的顺序又或者你是否正确导入了模型

例如,假设您的 Flask 应用的入口点是 run.py,您应该检查其中的导入语句和应用初始化代码。一个典型的 Flask 应用结构可能如下:

jsx 复制代码
# run.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = '您的数据库连接'
db = SQLAlchemy(app)

# 确保在 db.create_all() 调用之前导入所有模型
from models.store import Store
from models.device import Device
# ... 其他模型的导入 ...

@app.route('/')
def index():
    return "Welcome to the app!"

if __name__ == '__main__':
    db.create_all()  # 在应用上下文中创建所有数据库表
    app.run(debug=True)

在这个示例中,Store 模型在 Device 模型之前导入,因为 Device 依赖于 Storestore_id 字段是外键,指向 Store 表的主键)。如果 StoreDevice 在不同的文件中定义,这种导入顺序尤为重要。


| ✍️ 作者:ZouYu
| 🤳 微信号:19973318795

相关推荐
Asthenia041239 分钟前
Spring扩展点与工具类获取容器Bean-基于ApplicationContextAware实现非IOC容器中调用IOC的Bean
后端
bobz9651 小时前
ovs patch port 对比 veth pair
后端
Asthenia04121 小时前
Java受检异常与非受检异常分析
后端
uhakadotcom1 小时前
快速开始使用 n8n
后端·面试·github
JavaGuide1 小时前
公司来的新人用字符串存储日期,被组长怒怼了...
后端·mysql
bobz9652 小时前
qemu 网络使用基础
后端
Asthenia04122 小时前
面试攻略:如何应对 Spring 启动流程的层层追问
后端
Asthenia04122 小时前
Spring 启动流程:比喻表达
后端
Asthenia04123 小时前
Spring 启动流程分析-含时序图
后端
ONE_Gua3 小时前
chromium魔改——CDP(Chrome DevTools Protocol)检测01
前端·后端·爬虫