Python Django ORM 的工作原理
在 Web 开发中,处理数据库是非常常见的需求,尤其是在构建动态应用程序时。Django 作为一个流行的 Python Web 框架,提供了一套强大的工具帮助开发者轻松管理数据库。Django 的 ORM(对象关系映射,Object-Relational Mapping)就是其中的重要组成部分,它使开发者可以通过 Python 代码与数据库进行交互,而无需编写 SQL 语句。对于新手来说,理解 Django ORM 的工作原理将极大地简化数据库操作。
本文将深入解释 Django ORM 的基本原理,并通过具体的代码示例帮助你更好地理解如何使用它。

什么是 ORM?
在正式介绍 Django ORM 之前,首先了解一下 ORM 的基本概念。ORM(Object-Relational Mapping,对象关系映射)是一种将面向对象编程语言中的对象与关系型数据库中的表进行映射的技术。简单来说,它允许你在代码中通过对象操作数据库,而不是通过 SQL 语句。
ORM 的工作机制是通过将数据库表映射到模型类(Model),每个类的实例代表数据库中的一条记录。通过 ORM,你可以像操作 Python 对象一样操作数据库中的数据,这大大减少了学习 SQL 和写复杂查询的需求。
Django ORM 是 Django 框架内置的 ORM 系统,它通过模型类定义数据库结构,并允许你通过 Python 代码与数据库进行交互。接下来,我们将详细介绍 Django ORM 的工作流程。
Django ORM 的基本工作原理
在 Django 中,ORM 的主要职责是将 Python 对象与数据库表相关联。这包括以下几个核心步骤:
- 定义模型类:每个模型类都映射到数据库中的一张表,类的属性对应于表中的字段。
- 迁移数据库结构:Django 提供了迁移(migrations)机制,它可以将模型类的结构变化反映到数据库中,自动生成 SQL 语句并执行。
- 操作数据库:通过 Django ORM,开发者可以通过 Python 代码执行 CRUD 操作(创建、读取、更新和删除),而无需直接编写 SQL 语句。
- 查询优化和链式查询:ORM 提供了高效的查询工具,可以通过链式调用构建复杂的查询逻辑,并保证执行效率。
1. 定义模型类
在 Django 中,每个模型类都代表数据库中的一张表。要定义一个模型类,我们需要在应用的 models.py 文件中创建一个继承自 models.Model 的类。
例如,假设我们正在开发一个博客应用,需要一个用于存储文章的表。可以定义如下的模型类:
from django.db import modelsclass Post(models.Model):title = models.CharField(max_length=200)content = models.TextField()created_at = models.DateTimeField(auto_now_add=True)updated_at = models.DateTimeField(auto_now=True)def __str__(self):return self.title
在这个示例中,我们定义了一个 Post 类,表示博客文章。这个类有以下几个字段:
title: 文章标题,使用CharField,表示一个字符串字段,max_length=200限制了字符长度。content: 文章内容,使用TextField,用于存储大量文本。created_at: 文章创建的时间,使用DateTimeField,并且设置了auto_now_add=True,表示自动填充当前时间。updated_at: 文章更新时间,使用DateTimeField,并设置auto_now=True,每次文章更新时会自动修改这个字段。
每个字段类型(CharField、TextField、DateTimeField 等)都对应数据库中的数据类型,Django ORM 会根据这些定义生成相应的 SQL 语句。
2. 创建数据库迁移
模型类定义好之后,接下来需要将这些变化应用到数据库中。这是通过 Django 的迁移系统完成的。迁移是 ORM 用来跟踪和管理数据库表结构变化的工具,它可以自动生成 SQL 语句并应用到数据库。
执行以下命令来创建迁移文件:
python manage.py makemigrations
这个命令会扫描模型的变化,并生成相应的迁移文件。这些文件包含了创建或修改数据库表的 SQL 语句。接着,运行以下命令来应用迁移并将这些变化同步到数据库:
python manage.py migrate
当你运行 migrate 命令时,Django 会根据迁移文件生成 SQL 语句并执行,从而在数据库中创建或修改相应的表。
3. 操作数据库
当模型和数据库同步好之后,我们可以通过 Django ORM 来操作数据库了。Django ORM 提供了一些方便的方法来执行 CRUD(创建、读取、更新、删除)操作。
1. 创建数据
你可以通过模型类创建数据库记录。以下是创建一条新的博客文章的示例:
from blog.models import Post# 创建一篇新的文章
new_post = Post(title="我的第一篇文章", content="这是我的第一篇博客文章的内容。")
new_post.save() # 保存到数据库
在上面的代码中,我们首先实例化了 Post 类,传入文章的标题和内容。调用 save() 方法后,Django ORM 会生成一个 INSERT 语句,并将数据写入到数据库中。
2. 查询数据
Django ORM 提供了强大的查询功能,你可以使用 Post.objects 来查询 Post 表中的数据。
- 查询所有记录:
posts = Post.objects.all() # 返回所有文章对象的列表
- 按条件查询:
post = Post.objects.get(id=1) # 根据主键 id 查询单条记录
- 过滤查询:
recent_posts = Post.objects.filter(created_at__year=2024) # 查询 2024 年发布的文章
在这里,filter() 方法返回一个满足条件的查询集(QuerySet)。Django 的查询集支持链式调用,你可以通过多个条件组合成复杂的查询。
3. 更新数据
要更新一条记录,首先需要先查询出该记录,然后修改字段并调用 save() 方法。
post = Post.objects.get(id=1)
post.title = "更新后的标题"
post.save() # 保存更改
Django ORM 会生成一个 UPDATE 语句,将修改后的数据更新到数据库。
4. 删除数据
要删除一条记录,你可以使用 delete() 方法:
post = Post.objects.get(id=1)
post.delete() # 删除这条记录
delete() 方法会生成 DELETE 语句,并从数据库中删除该记录。
4. 查询优化与链式查询
Django ORM 的查询集是惰性执行的,这意味着查询操作不会立即访问数据库,只有当需要访问结果时才会执行 SQL 查询。这种惰性执行机制提高了性能,因为它允许 Django 构建复杂的查询链,而无需在每一步都访问数据库。
1. 链式查询
你可以通过链式调用将多个查询条件组合起来。以下是一个示例:
posts = Post.objects.filter(title__contains="Django").filter(created_at__year=2024)
在这个示例中,filter() 方法被调用了两次,最终的 SQL 查询将包含两个条件,查询标题中包含 “Django” 且在 2024 年创建的文章。
2. 查询优化
Django ORM 还提供了查询优化工具,例如 select_related() 和 prefetch_related(),用于优化涉及外键和多对多关系的查询。
select_related():用于减少外键查询的数据库访问次数。它通过一个JOIN操作一次性获取相关表的数据。
posts = Post.objects.select_related('author').all() # 假设 Post 表有一个外键指向 Author 表
prefetch_related():用于处理多对多关系的查询优化。它通过执行两次独立查询来减少数据库访问次数。
posts = Post.objects.prefetch_related('tags').all() # 假设 Post 表有一个多对多的 tags 关系
通过这些查询优化工具,你可以显著提高数据库查询的效率,尤其在处理大型项目或复杂的数据库结构时。
Django ORM 的高级功能
除了基本的 CRUD 操作,Django ORM 还提供了一些高级功能,帮助开发者更灵活地与数据库进行交互。
1. 模型继承
Django 支持模型继承,这意味着你可以创建一个基类模型,并让其他模型从它继承字段和方法。以下是一个示例:
class BaseModel(models.Model):created_at = models.DateTimeField(auto_now_add=True)updated_at = models.DateTimeField(auto_now=True)class Meta:abstract = True # 抽象基类,不会生成表class Post(BaseModel):title = models.CharField(max_length=200)content = models.TextField()
在这个示例中,BaseModel 是一个抽象基类,它定义了 created_at 和 updated_at 字段。Post 类继承了这个基类,并自动拥有这两个字段。
2. 自定义管理器
Django ORM 允许你创建自定义管理器(Manager)来扩展查询集的功能。例如,假设我们想创建一个自定义查询集,只返回最近发布的文章,可以这样实现:
class PostManager(models.Manager):def recent_posts(self):return self.filter(created_at__gte=datetime.now()-timedelta(days=30))class Post(models.Model):title = models.CharField(max_length=200)content = models.TextField()objects = PostManager() # 使用自定义管理器
现在我们可以调用 Post.objects.recent_posts() 来获取最近 30 天内发布的文章。
结论
Django ORM 提供了强大而灵活的工具,帮助开发者通过 Python 代码与数据库交互。它将面向对象编程的理念引入到数据库操作中,大大减少了编写 SQL 的需求,简化了 Web 开发中的数据库管理工作。通过本文的介绍,你应该能够理解 Django ORM 的基本原理,并开始在项目中使用它进行数据库操作。
相关文章:
Python Django ORM 的工作原理
在 Web 开发中,处理数据库是非常常见的需求,尤其是在构建动态应用程序时。Django 作为一个流行的 Python Web 框架,提供了一套强大的工具帮助开发者轻松管理数据库。Django 的 ORM(对象关系映射,Object-Relational Map…...
GoLang编程常用规范/工具
代码格式化工具 代码风格: go install github.com/fsgo/go_fmt/cmd/gorgeouslatest gorgeous # 仅格式化git有改动的文件。如需格式化所有文件,可以执行 gorgeous ./...标签格式:https://github.com/4meepo/tagalign go install github.c…...
数字王国里的虚拟人――技术、商业与法律解读
💂 个人网站:【 摸鱼游戏】【神级代码资源网站】【海拥导航】🤟 找工作,来万码优才:👉 #小程序://万码优才/HDQZJEQiCJb9cFi💅 想寻找共同学习交流,摸鱼划水的小伙伴,请点击【全栈技…...
Java后端基础练习|请求参数
请求参数,可以通过四种方式传递到后端 请求路径查询参数请求体请求头 controller代码 package com.urfread.breaknews.core.controller;import com.urfread.breaknews.core.common.model.ResultData; import lombok.Data; import org.springframework.web.bind.a…...
C# + SQLiteExpert 进行(cipher)加密数据库开发+Costura.Fody 清爽发布
一:让 SQLiteExpert 支持(cipher)加密数据库 SQLiteExpert 作为SQlite 的管理工具,默认不支持加密数据库的,使其成为支持(cipher)加密数据库的管理工具,需要添加e_sqlcipher.dll &…...
MySQL 8.0 新特性之自增变量持久化
MySQL 8.0 新特性之自增变量持久化 文章目录 MySQL 8.0 新特性之自增变量持久化MySQL 5.7 vs 8.0 测试对比MySQL 5.7MySQL 8.0 参考资料 MySQL 8.0 中支持自增变量持久化,实际也是解决之前版本中存在的自增主键重启重置的 BUG 问题( BUG #199࿱…...
网站建设公司哪家好?好的网站建设公司应该有哪些特别之处?
面对众多的网站建设公司,企业该如何选择呢?如何才能避坑呢?本文将探讨好的网站建设公司应该具备的特别之处 案例,这是最直观的表现,一个好的网站建设公司必然拥有为数众多的的案例展示,且这些案例质量高&a…...
香山南湖架构分析--FE
总体架构 分支预测和指令缓存,通过FTQ达到解耦的目的;FTQ将请求送给ICache,进行取指;取出的指令码通过预译码初步检查分支预测的错误并及时冲刷预测流水线;检查后的指令送入指令缓冲并传给译码模块,最终形成后端的指令…...
【Linux的那些事】shell命名及Linux权限的理解
目录 一、shell命令以及运行原理 二、Linux权限的概念 三、Linux权限管理 3.1.文件访问者的分类(人) 3.2.文件类型和访问权限(事物属性) 3.3.文件权限值的表示方法 3.4.文件访问权限的相关设置方法 a)chmod b)chown c)…...
Visual Studio 2022 配置 Boost 库
一、使用预编译版本 尽量不要使用预编译版本,因为可能构建的不完全,还得重新构建,不如一步到位 1. 下载预编译的 Boost 库 下载:Boost C Libraries - Browse /boost-binaries at SourceForge.net 2. 选择 msvc 版本࿰…...
逻辑回归(下): Sigmoid 函数的发展历史
背景 闲来无事翻了一下之前买的一个机器学习课程及之前记录的网络笔记,发现遇到公式都是截图,甚至是在纸上用笔推导的。重新整理一遍之前逻辑回归函数的学习笔记,主要是为了玩一下 LaTex 语法,写公式挺有意思的。 整理之前三篇笔…...
快速理解mQ(三)——RabbitMQ 各种交换机的区别与应用
RabbitMQ是一个开源的消息代理软件,它实现了高级消息队列协议(AMQP),允许应用程序或系统以异步的方式交换数据。RabbitMQ中的交换机(Exchange)是消息的分发中心,它接收来自生产者的消息…...
【五分钟学会】YOLO11 自定义数据集从训练到部署
数据集地址 数据集包含 360 张红血细胞图像及其注释文件,分为训练集与验证集。训练文件夹包含 300 张带有注释的图像。测试和验证文件夹都包含 60 张带有注释的图像。我们对原始数据集进行了一些修改以准备此 CBC 数据集,并将数据集分成三部分。在360张…...
Redis学习(十二)连接数不足报错及分析修复:ERR max number of clients reached.
目录 一、问题介绍二、问题分析2.1 redis-cli 登录2.2 info clients 查看连接数情况2.3 client list 查看具体连接情况2.4 分析连接空闲时长2.5 client list 根据客户端IP统计连接数 三、问题结论和解决3.1 问题结论:3.2 解决方案①:优化程序3.3 解决方案…...
八股文面试题总结(包含主流的面试经典题)
Java基础 1、JDK和JRE的区别是什么** JDK是Java开发工具包,JRE是Java运行时环境,二者的区别在于 JRE是Java程序运行所必须的,它包含jvm和一些Java的基础类库 JDK是Java程序开发所必须的,它包含JRE和一些开发工具 总结一下就是…...
一分钟掌握 Java22 新特性
1. 增强的模式匹配(Pattern Matching for Switch) Java 22 扩展了模式匹配的功能,允许在 switch 语句中使用模式匹配,从而使代码更加简洁和易读。 示例代码: public class PatternMatchingSwitchDemo {public stati…...
西安凭借入驻企业展示科技“硬”实力的数字媒体产业园
在古城西安的怀抱中,一座以科技“硬”实力为核心竞争力的数字媒体产业园——西安国际数字影像产业园,正以其独特的魅力和无限的潜力,吸引着全球的目光。这里,不仅是数字创意的孵化场,更是科技创新的策源地。 西安国际数…...
【网络安全】利用XSS、OAuth配置错误实现token窃取及账户接管 (ATO)
未经许可,不得转载。 文章目录 正文正文 目标:target.com 在子域sub1.target.com上,我发现了一个XSS漏洞。由于针对该子域的漏洞悬赏较低,我希望通过此漏洞将攻击升级至app.target.com,因为该子域的悬赏更高。 分析认证机制后,我发现: sub1.target.com:使用基于Cook…...
浙江所有省级医院体检报告查询上线浙里办!
在医院完成体检后不知道什么时候出报告 体检报告出来后又要跑一次医院去拿报告 历年体检报告没保管好 往年体检报告找不到了 ………… 编辑 为解决这些问题,浙江省卫生健康委结合“两卡融合、一网通办”工作的推进,不断丰富电子健康医保卡的功能&#…...
支付宝支付Java+uniapp支付宝小程序
JS: request.post(/vip/pay, {//这是自己写的java支付接口id: this.vipInfo.id,payWay: alipay-mini}).then((res) > {let success (res2) > {//前端的支付成功回调函数this.$refs.popup.close();// 支付成功刷新当前页面setTimeout(() > {this.doGetVipI…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
《信号与系统》第 6 章 信号与系统的时域和频域特性
目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...
基于单片机的宠物屋智能系统设计与实现(论文+源码)
本设计基于单片机的宠物屋智能系统核心是实现对宠物生活环境及状态的智能管理。系统以单片机为中枢,连接红外测温传感器,可实时精准捕捉宠物体温变化,以便及时发现健康异常;水位检测传感器时刻监测饮用水余量,防止宠物…...
【大模型】RankRAG:基于大模型的上下文排序与检索增强生成的统一框架
文章目录 A 论文出处B 背景B.1 背景介绍B.2 问题提出B.3 创新点 C 模型结构C.1 指令微调阶段C.2 排名与生成的总和指令微调阶段C.3 RankRAG推理:检索-重排-生成 D 实验设计E 个人总结 A 论文出处 论文题目:RankRAG:Unifying Context Ranking…...
