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

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。模型类代表数据库表,类中的属性代表表中的列。例如:

from flask_sqlalchemy import SQLAlchemydb = 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 允许在模型间建立一对多、多对一或多对多的关系。例如,一个店铺拥有多个设备的一对多关系可以这样定义:

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 中的关联进行查询

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

store = Store.query.get(some_store_id)
devices = store.devices

实现示例

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

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

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

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

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 模型中:

class Device(db.Model):# ...store = db.relationship('Store', back_populates='devices')

Store 模型中:

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 为这种关系提供了一个更为直观和方便的操作接口,但它只存在于代码层面,不直接映射到数据库结构中。
  • 这种设计使得应用程序的后端开发更加简洁和直观,同时保持了数据库的完整性和效率。

模型的导入

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

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 应用结构可能如下:

# run.pyfrom flask import Flask
from flask_sqlalchemy import SQLAlchemyapp = 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 在不同的文件中定义,这种导入顺序尤为重要。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/146144.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ES聚合与分组查询取值参数含义(Java api版本)

一、说明 在项目中使用Elasticsearch的聚合与分组查询后,对于返回结果一脸懵逼,查阅各资料后,自己总结了一下参数取值的含义,不一定全面,只含常见参数 二、分组查询 2.1 参数解释 SearchResponse<Map> searchResponse null;try {searchResponse client.search(s ->…

【论文阅读】VideoComposer: Compositional Video Synthesis with Motion Controllability

VideoComposer&#xff1a; 具有运动可控性的合成视频。 paper&#xff1a;[2306.02018] VideoComposer: Compositional Video Synthesis with Motion Controllability (arxiv.org) 由阿里巴巴研发的可控视频生成框架&#xff0c;可以灵活地使用文本条件、空间条件和时序条件…

各机构如何加强网络渗透、“渗透”防御

数据渗透&#xff0c;例如黑客攻击和“渗透”&#xff0c;或未经授权的信息传输。 联邦调查局、国家安全局以及网络安全和基础设施安全局最近的联合报告证明&#xff0c;网络安全仍然是当今国防部门面临的两个最大的网络威胁。 所谓的零日攻击尤其有害&#xff0c;因为组织在…

pytorch单精度、半精度、混合精度、单卡、多卡(DP / DDP)、FSDP、DeepSpeed模型训练

pytorch单精度、半精度、混合精度、单卡、多卡&#xff08;DP / DDP&#xff09;、FSDP、DeepSpeed&#xff08;环境没搞起来&#xff09;模型训练代码&#xff0c;并对比不同方法的训练速度以及GPU内存的使用 代码&#xff1a;pytorch_model_train FairScale&#xff08;你真…

Apache阿帕奇安装配置

目录 一、下载程序 1. 点击Download 2. 点击Files for Microsoft Windows 3. 点击Apache Lounge 4. 点击httpd-2.4.54-win64-VSI6.zip ​5. 下载压缩包 6.解压到文件夹里 二、配置环境变量 1. 右键我的电脑 - 属性 2. 高级系统设置 3. 点击环境变量 4. 点击系统变…

瑞吉外卖Day06

1.用户地址 1.1实体类 /*** 地址簿*/ Data public class AddressBook implements Serializable {private static final long serialVersionUID 1L;private Long id;//用户idprivate Long userId;//收货人private String consignee;//手机号private String phone;//性别 0 女…

【蓝桥杯省赛真题01】C++水下探测器 第十届蓝桥杯中小学生创意编程大赛C++编程比赛省赛真题解析

目录 C/C++水下探测器 一、题目要求 1、编程实现 2、输入输出 二、算法分析

C++初阶:STL之string类

一.为什么学习string类&#xff1f; 在C语言中没有字符串这一数据类型&#xff0c;都是用字符数组来处理字符串&#xff0c;C也支持这种C风格的字符串。除此之外&#xff0c;C还提供了一种自定义数据类型--string&#xff0c;string是C标准模板库(STL)中的一个字符串类&#x…

《Effective C++》条款21

必须返回对象时&#xff0c;别妄想返回其reference 如果你的运算符重载函数写成了返回reference的形式&#xff1a; class A { public:A(int a,int b):x(a),y(b){}friend const A& operator*(const A& a, const A& b); private:int x;int y; }; const A& opera…

大型语言模型中的幻觉研究综述:原理、分类、挑战和未决问题11.15+11.16+11.17

大型语言模型中的幻觉研究综述&#xff1a;原理、分类、挑战和未决问题11.15 摘要1 引言2 定义2.1 LLM2.3 大语言模型中的幻觉 3 幻觉的原因3.1 数据的幻觉3.1.1 有缺陷的数据源3.1.2 较差的数据利用率3.1.3 摘要 3.2 来自训练的幻觉3.2.1训练前的幻觉3.2.2来自对齐的幻觉3.2.3…

易点易动固定资产管理系统场景应用一:集成ERP/财务系统

在企业的日常运营中&#xff0c;固定资产管理是一个重要而繁琐的任务。传统的手工管理方式往往效率低下且容易出错&#xff0c;给企业带来不必要的成本和风险。为了解决这一问题&#xff0c;易点易动固定资产管理系统应运而生。本文将重点介绍易点易动固定资产管理系统在集成ER…

清理mac苹果电脑磁盘软件有哪些免费实用的?

苹果电脑是一款非常流行的操作系统设备&#xff0c;其稳定性和性能一直备受用户的喜爱。然而&#xff0c;随着时间的推移&#xff0c;我们使用电脑的过程中可能会发现磁盘上存储的数据越来越多&#xff0c;这不仅占用了宝贵的硬盘空间&#xff0c;还可能导致电脑运行变慢。因此…

kotlin--3.集合操作

目录 一.list集合 二.Set集合 三.Map集合 迭代遍历Map集合&#xff1a; 8.hashMap 四.Stream流 1.map 2.filter 3.reduce 4.forEach 5.sorted 6.distinct 7.综合案例 一.list集合 在Kotlin中&#xff0c;常见的List集合类型有以下几种&#xff1a; listOf&…

【Shell实战】Linux多节点分发文件

多节点分发文件 通过shell脚本将跳板机或者软件中转机上的文件&#xff0c;分发至一组目标机器中。 使用前提&#xff1a; 跳板机或者软件中转机与目标集群均配置免密。目标机器的接收目录拥有足够的大小。 脚本使用说明&#xff1a; sh distributing_packages.sh /data/g…

微服务实战系列之Token

前言 什么是“Token”&#xff1f; 它是服务端生成的一串字符串&#xff0c;以作客户端进行请求的一个令牌&#xff0c;当第一次登录后&#xff0c;服务器生成一个Token便返回给客户端&#xff1b;以后客户端只携带此Token请求数据即可。 简言之&#xff0c;Token其实就是用户身…

数据结构与算法之美学习笔记:20 | 散列表(下):为什么散列表和链表经常会一起使用?

目录 前言LRU 缓存淘汰算法Redis 有序集合Java LinkedHashMap解答开篇 & 内容小结 前言 本节课程思维导图&#xff1a; 今天&#xff0c;我们就来看看&#xff0c;在这几个问题中&#xff0c;散列表和链表都是如何组合起来使用的&#xff0c;以及为什么散列表和链表会经常…

3ds Max渲染用专业显卡还是游戏显卡?

使用3dsmax建模时&#xff0c;会面临诸多选择&#xff0c;除了用vr还是cr的决策&#xff0c;硬件选择上也存在着疑问&#xff0c;比如用专业显卡还是消费级游戏显卡&#xff1f;一般来说&#xff0c;除非是特别专业的大型项目和软件&#xff0c;且预算在5位数以上&#xff0c;常…

Android Glide加载transform CenterCrop, CircleCrop ShapeableImageView圆形图并描边,Kotlin

Android Glide加载transform CenterCrop, CircleCrop ShapeableImageView圆形图并描边&#xff0c;Kotlin import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.bumptech.glide.load.resource.bitmap.CenterCrop import com.bumptech.glide.…

代码随想录算法训练营第二十五天| 216 组合总合 ||| 17 电话号码的字母组合

216 组合总和 ||| 暴力 class Solution {List<List<Integer>>res new ArrayList<>();List<Integer>newList new ArrayList<>();public List<List<Integer>> combinationSum3(int k, int n) {soluHelper(1,k,n,0);return res;}pr…

qt笔记之qml和C++的交互系列(一):初记

code review! —— 杭州 2023-11-16 夜 文章目录 一.qt笔记之qml和C的交互&#xff1a;官方文档阅读理解0.《Overview - QML and C Integration》中给出五种QML与C集成的方法1.Q_PROPERTY&#xff1a;将C类的成员变量暴露给QML2.Q_INVOKABLE()或public slots&#xff1a;将C类…