当前位置: 首页 > news >正文

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 在不同的文件中定义,这种导入顺序尤为重要。


相关文章:

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

SQLAlchemy 在 Flask 应用中的使用和最佳实践 [TOC](SQLAlchemy 在 Flask 应用中的使用和最佳实践) 模型的编写**SQLAlchemy 中建立关联****利用 SQLAlchemy 中的关联进行查询****实现示例** backref与back_populates?**backref反向引用****back_populates后填充** …...

FineReport -问题学习图表设计图表类型-单元格扩展父子格-报表预览

1,问:为什么本地每次预览都要填帐号密码?答:模板认证关闭一下及可 2.单元格扩展与父子格----左父格-扩展方向-箭头往那个方向就往那个方向 1)数据集参数 在定义数据集时,通过使用if函数判断参数的值是否为空,若为空就不过滤参数,若不为空就进行参数过滤。SELECT * FROM…...

微信小程序广告banner、滚动屏怎么做?

使用滑块视图容器swiper和swiper-item可以制作滚动屏&#xff0c;代码如下&#xff1a; wxml: <swiper indicator-dots indicator-color"rgba(255,255,255,0.5)" indicator-active-color"white" autoplay interval"3000"><swiper-ite…...

Network(一)计算机网络介绍

一 计算机网络 1 概述 什么是计算机网络&#xff1f; 硬件方面:通过线缆将网络设备和计算机连接起来 软件方面:操作系统&#xff0c;应用软件&#xff0c;应用程序通过通信线路互连 实现资源共享、信息传递、增加可靠性、提高系统处理能力 2 网络与云计算 3 计算机网…...

【数据结构】堆(Heap):堆的实现、堆排序、TOP-K问题

目录 堆的概念及结构 ​编辑 堆的实现 实现堆的接口 堆的初始化 堆的打印 堆的销毁 获取最顶的根数据 交换 堆的插入&#xff08;插入最后&#xff09; 向上调整&#xff08;这次用的是小堆&#xff09; 堆的删除&#xff08;删除根&#xff09; 向下调整&#xff08;这次用的…...

保护数字前沿:下一代防火墙如何塑造网络安全的未来

下一代防火墙通过提供先进的威胁检测、精细控制和云安全功能&#xff0c;正在重塑网络安全的未来。随着数字环境的不断发展&#xff0c;组织必须采用这些创新解决方案来保护其数字资产并维护安全的数字前沿。 在当今互联的世界中&#xff0c;网络威胁变得越来越复杂&#xff0c…...

深入理解Java中的String.join方法

在 Java 编程中&#xff0c;字符串操作是非常常见的需求。在 Java 8 中引入了一个方便的字符串连接方法 String.join&#xff0c;它能够简洁而高效地将多个字符串连接起来。本篇博客将深入介绍 String.join 方法的使用和原理。 什么是String.join方法&#xff1f; String.join…...

【MySQL系列】 第三章 · 函数

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…...

微信小程序wxss定位/选择/查找元素的几种方式

wxss定位、选择、查找元素的几种方式与css类似&#xff0c;下面介绍常用的几种&#xff1a; 选择器样例样例描述.class.intro选择所有拥有 class"intro" 的组件#id#firstname选择拥有 id"firstname" 的组件elementview选择所有 view 组件element, element…...

Canvas—从入门到案例实现

文章目录 Canvas—从入门到案例实现一、设置canvas环境1.1 <canvas>元素1.2 渲染上下文context 二、形状与路径的绘制2.1 形状绘制2.2 路径绘制2.3 绘制一个笑脸 三、使用样式和颜色四、绘制文本五、使用图像5.1 图片源5.2 获取页面内的图片5.3 缩放Scaling5.4 切片Slici…...

飞书开发学习笔记(六)-网页应用免登

飞书开发学习笔记(六)-网页应用免登 一.上一例的问题修正 在上一例中&#xff0c;飞书登录查看网页的界面显示是有误的&#xff0c;看了代码&#xff0c;理论上登录成功之后&#xff0c;应该显示用户名等信息。 最后的res.nickName是用户名&#xff0c;res.i18nName.en_us是英…...

【ROS】Nav2源码下载、编译、运行

【ROS】郭老二博文之:ROS目录 1、源码下载 1.1 源码地址 https://github.com/ros-planning/navigation2 1.2 创建工程目录 ROS2使用目录结果来管理项目,因此在下载前需要创建好目录结构: mkdir -p ~/git/nav2/src1.3 下载 git中默认版本是main。本人的开发环境为Ubun…...

微信小程序 30分钟倒计时功能

ps:凑个数 getTimeDiff(date) {let _this = this;let curTime = new Date(date)_this.countDown(_this.timeFormatConvert(new Date(curTime.setMinutes(curTime.getMinutes() + 30))))},timeFormatConvert(e) {const Y = e.getFullYear(); // 年const M = this.prefixZero(e.…...

JAVA判断指定日期是否在指定的时间段内

参考文献: Java语言判断当前时间在时间范围内_java判断时间区间-CSDN博客 package com.itheima.method2;import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date;public class DateTest {public static voi…...

关于晋升与跳槽的一些思考

内部晋升 内部晋升是我优先考虑的&#xff0c;原因有很多。首先这是一个新业务&#xff0c;相对而言容易拿到结果。其次我想体验不同的晋升路径&#xff0c;内部晋升答辩&#xff0c;是挑战也是一次成长的机会&#xff0c;是一次他人帮助自己review的机会。作为从校园出来的校…...

url找不到404的问题,url被拼接

今天遇到一个测试feign调用的功能&#xff0c;如图所示 先说结论 Controller换成RestController 将日志设置为debug模式 被DispatcherServlet FORWARD了 找到路径 对属性设置断点&#xff0c;看下是哪注进来的 我们再去找encodedPath 此处是undertow的源码&#xff0c;但是und…...

如何解决golang开发中遇到的报错:checksum mismatch downloaded

问题描述 如题&#xff0c;项目开发中遇到如下报错&#xff08;你的报错信息可能与我的有一点区别&#xff0c;如verifying的包名&#xff0c;但是问题本质都是一样的&#xff09;&#xff1a; verifying github.com/algorand/go-codec/codecv1.1.8/go.mod: checksum mismatc…...

4.以docker容器生成镜像推送到阿里云镜像仓库

1.开通阿里云镜像仓库 1.1 登录阿里云&#xff0c;访问容器镜像服务。地址如下&#xff1a; https://cr.console.aliyun.com/cn-shanghai/instances 1.2 个人学习为例&#xff0c;创建个人版实例 1.2.1 点击个人实例 1.2.2 .创建个人实例 1.2.3 创建完成后&#xff0c;设置…...

CSS Form表单布局

效果图 <Tab IsCard"true"><TabItem Text"表单信息-DIV版本"><div class"row"><div class"col"><label for"field1">工程名称:</label><input class"form-control" type&…...

c++ shared_mutex 读写锁使用详解

c 读写锁使用详解 std::shared_mutex c17 头文件 #include <shared_mutex>。用于实现共享和独占访问的互斥锁。提供了一种更加灵活的机制&#xff0c;允许多个线程在共享模式下读取数据&#xff0c;但只允许单个线程在独占模式下写入或修改数据。与 std::mutex 相比&am…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...