Django ORM 的常用字段类型、外键关联的跨表引用技巧,以及 `_` 和 `__` 的使用场景
一、Django ORM 常用字段类型
1. 基础字段类型
| 字段类型 | 说明 | 示例 |
|---|---|---|
CharField | 字符串字段,必须指定 max_length | name = models.CharField(max_length=50) |
IntegerField | 整数字段 | age = models.IntegerField() |
BooleanField | 布尔值字段 | is_active = models.BooleanField() |
DateField / DateTimeField | 日期/日期时间字段,auto_now_add=True 自动设置创建时间 | created_at = models.DateTimeField(auto_now_add=True) |
EmailField | 专用于邮箱的 CharField(自带基础格式验证) | email = models.EmailField() |
TextField | 长文本字段(不限长度) | content = models.TextField() |
FileField / ImageField | 文件/图片上传字段(需 Pillow 库支持 ImageField) | avatar = models.ImageField(upload_to='avatars/') |
2. 关联字段类型
| 字段类型 | 说明 | 示例 |
|---|---|---|
ForeignKey | 外键(一对多关联) | author = models.ForeignKey('Author', on_delete=models.CASCADE) |
OneToOneField | 一对一关联(常用于扩展用户模型) | profile = models.OneToOneField(User, on_delete=models.CASCADE) |
ManyToManyField | 多对多关联(自动创建中间表) | tags = models.ManyToManyField('Tag') |
关键参数说明:
on_delete: 关联对象删除时的行为(必填),常见选项:CASCADE: 级联删除(默认)SET_NULL: 设为null(需字段允许null=True)PROTECT: 阻止删除
related_name: 反向查询时的名称(默认模型名_set,如book_set)
二、跨表引用技巧
1. 正向查询(直接通过外键访问)
# 模型定义
class Author(models.Model):name = models.CharField(max_length=100)class Book(models.Model):title = models.CharField(max_length=100)author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="books")# 示例:查询某本书的作者
book = Book.objects.get(id=1)
author_name = book.author.name # 直接通过外键访问
2. 反向查询(通过关联模型反向访问)
# 示例:查询某作者的所有书籍
author = Author.objects.get(id=1)
books = author.books.all() # 使用 related_name 定义的名称(默认是 book_set)
3. 跨表过滤(使用双下划线 __)
# 查询所有书籍的作者名为 "鲁迅" 的书籍
books = Book.objects.filter(author__name="鲁迅")# 查询作者出版过书籍数量大于 5 的作者
authors = Author.objects.annotate(book_count=Count('books')).filter(book_count__gt=5)
三、_ 和 __ 的使用技巧
1. 单下划线 _
- 用途:用于关联字段的数据库列名或 ORM 内部操作。
- 示例:
# 访问外键的数据库列名(author_id) book = Book.objects.get(id=1) author_id = book.author_id # 直接获取外键值(无需访问关联对象)# 查询时直接使用字段名 Book.objects.filter(author_id=1)
2. 双下划线 __
- 用途:跨表查询时连接关联模型的字段(可链式跨多张表)。
- 示例:
# 查询作者所在城市为 "北京" 的书籍 Book.objects.filter(author__city="北京")# 多级跨表:查询书籍的作者的出版社名称 Book.objects.filter(author__publisher__name="人民出版社")
3. 双下划线与查询表达式结合
# 查询价格大于 100 且作者年龄小于 30 的书籍
Book.objects.filter(price__gt=100, author__age__lt=30)# 查询书名以 "Django" 开头或作者邮箱包含 "@example.com"
from django.db.models import Q
Book.objects.filter(Q(title__startswith="Django") | Q(author__email__contains="@example.com"))
四、总结
核心技巧
-
字段类型选择:
- 根据数据类型选择合适字段(如
CharFieldvsTextField)。 - 关联字段注意
on_delete和related_name的设置。
- 根据数据类型选择合适字段(如
-
跨表查询:
- 正向查询:直接通过外键字段访问关联对象。
- 反向查询:使用
related_name或默认的模型名_set。 - 复杂查询:通过
__跨表连接字段。
-
_vs__:_用于数据库列名或单级字段访问(如author_id)。__用于跨表查询(如author__name)。
性能优化
- 使用
select_related预加载外键数据(减少查询次数):books = Book.objects.select_related('author').all() # 一次性加载作者信息 - 使用
prefetch_related预加载多对多关系:authors = Author.objects.prefetch_related('books').all() # 预加载所有书籍
通过灵活组合这些技巧,可以高效操作 Django ORM 处理复杂的数据关系!
好的!反向查询是 Django ORM 中通过关联模型(比如外键的“被关联方”)去访问发起关联的模型的关键操作。它让跨表查询更灵活,下面用详细的示例和场景帮你彻底理解。
一、反向查询的核心原理
假设有两个模型:Author(作者)和 Book(书籍),通过外键关联:
class Author(models.Model):name = models.CharField(max_length=100)class Book(models.Model):title = models.CharField(max_length=100)author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')
- 正向查询:从
Book访问Author(直接通过外键字段author)。 - 反向查询:从
Author访问所有关联的Book对象(需要借助related_name或默认的book_set)。
二、反向查询的两种方式
1. 使用默认的 模型名_set
如果未设置 related_name,Django 会自动生成反向查询管理器,格式为:关联模型名的小写 + _set。
# 假设 Book 模型的外键未设置 related_name
class Book(models.Model):author = models.ForeignKey(Author, on_delete=models.CASCADE)# 反向查询:通过 author.book_set 访问所有书籍
author = Author.objects.get(id=1)
books = author.book_set.all() # 获取该作者的所有书籍
2. 使用自定义的 related_name
通过设置 related_name,可以指定更直观的反向查询名称:
class Book(models.Model):author = models.ForeignKey(Author, on_delete=models.CASCADE,related_name='books' # 自定义反向查询名称)# 反向查询:通过 author.books 访问所有书籍
author = Author.objects.get(id=1)
books = author.books.all() # 更直观的命名
三、反向查询的常见操作
1. 获取关联对象集合
# 查询作者 "鲁迅" 的所有书籍
author = Author.objects.get(name="鲁迅")
books = author.books.all() # 返回 QuerySet
2. 过滤关联对象
# 查询作者 "鲁迅" 的出版年份大于 2020 的书籍
books = author.books.filter(publish_year__gt=2020)
3. 创建新的关联对象
# 为作者 "鲁迅" 创建一本新书
new_book = author.books.create(title="狂人日记", publish_year=1918)
4. 统计关联对象数量
# 统计作者 "鲁迅" 的书籍数量
book_count = author.books.count()
四、反向查询在跨表过滤中的使用
反向查询结合双下划线 __,可以在查询条件中直接穿透关联模型。
场景1:查询所有写过“小说”类书籍的作者
# 模型扩展:书籍增加分类字段
class Book(models.Model):CATEGORY_CHOICES = [('novel', '小说'),('tech', '科技'),]category = models.CharField(max_length=10, choices=CATEGORY_CHOICES)author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')# 反向查询:直接通过 Author 模型过滤
authors = Author.objects.filter(books__category='novel').distinct()
books__category:从Author穿透到Book的category字段。distinct():避免重复作者(如果同一作者有多本小说)。
场景2:查询书籍平均评分大于 4.5 的作者
from django.db.models import Avg# 模型扩展:书籍增加评分字段
class Book(models.Model):rating = models.FloatField(default=0)author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')# 使用 annotate + 反向查询
authors = Author.objects.annotate(avg_rating=Avg('books__rating')
).filter(avg_rating__gt=4.5)
五、反向查询的性能优化
1. 使用 prefetch_related 预加载数据
避免 N+1 查询问题(遍历作者时,每次访问 author.books 都会触发一次查询):
# 未优化:触发多次查询
authors = Author.objects.all()
for author in authors:print(author.books.all()) # 每次循环触发一次查询# 优化后:一次性预加载所有作者的书籍
authors = Author.objects.prefetch_related('books').all()
for author in authors:print(author.books.all()) # 无额外查询
2. 结合 select_related 和 prefetch_related
select_related:用于外键(一对一、多对一)的预加载。prefetch_related:用于多对多、反向查询的预加载。
# 同时预加载作者和书籍的出版社(假设 Book 有外键到 Publisher)
authors = Author.objects.prefetch_related(Prefetch('books', queryset=Book.objects.select_related('publisher'))
).all()
六、总结:反向查询的核心技巧
| 操作 | 代码示例 | 说明 |
|---|---|---|
| 基本反向查询 | author.books.all() | 获取所有关联对象 |
| 过滤关联对象 | author.books.filter(title__contains="Django") | 根据条件筛选关联对象 |
| 跨表过滤 | Author.objects.filter(books__rating__gt=4) | 在查询条件中使用反向关联字段 |
| 聚合统计 | Author.objects.annotate(book_count=Count('books')) | 统计每个作者的书籍数量 |
| 预加载优化 | prefetch_related('books') | 减少数据库查询次数 |
关键点:
- 始终优先使用
related_name自定义反向查询名称(代码更清晰)。 - 在复杂查询中灵活使用双下划线
__穿透关联模型。 - 大数据量时用
prefetch_related或select_related优化性能。
通过反向查询,你可以轻松实现从“一”对“多”或“多对多”关系的反向导航,让数据关联操作更加灵活高效!
相关文章:
Django ORM 的常用字段类型、外键关联的跨表引用技巧,以及 `_` 和 `__` 的使用场景
一、Django ORM 常用字段类型 1. 基础字段类型 字段类型说明示例CharField字符串字段,必须指定 max_lengthname models.CharField(max_length50)IntegerField整数字段age models.IntegerField()BooleanField布尔值字段is_active models.BooleanField()DateFiel…...
(动态规划 最长递增的子序列)leetcode 300
这道题我第一眼反应就是暴力,但是暴力的话就是n*n-1*n-2*...n-(n-1) 也就是O(n^n)dfs做绝对超时 贪心也不行,这里是子序列,要考虑在ni的范围内考虑多种路线取最优,所以用动态规划 如何用动态规划呢? 答:…...
小皮网站搭建
前提:小皮的安装下载 1、在www目录下创建一个新的文件夹,用来存放网站源码; 2、安装数据库管理工具phpMyadmin 3、新建数据表 添加字段 4、创建网站 5、前端的登录代码 注册 后端php 网页展示 登录成功跳转welcome.php...
3.16 AI Agent 技术全景解析:从核心能力到企业级应用实践
AI Agent 技术全景解析:从核心能力到企业级应用实践 关键词:AI Agent 技术架构, 大模型智能体开发, 自主决策系统设计, 模块化 Agent 设计, 企业级 Agent 应用 1. AI Agent 的本质定义与核心能力 AI Agent 是具备环境感知、自主决策和持续进化能力的智能系统,其核心特征可…...
【CSS—前端快速入门】CSS 常用样式
CSS 常用 CSS 样式 1. 前端样式查询网站: MDN Web Docs (mozilla.org) w3school 2. border 2.1 借助 MDN 了解 border 我们借助 MDN 网站来学习 border 样式的使用: 2.2 border 常见属性 保存代码,打开页面: 对于标签不同样式的…...
(七)消息队列-Kafka 序列化avro(传递)
(七)消息队列-Kafka 序列化avro(传递) 客从远方来,遗我双鲤鱼。呼儿烹鲤鱼,中有尺素书。 ——佚名《饮马长城窟行》 本文已同步CSDN、掘金平台、知乎等多个平台,图片依然保持最初发布的水印&…...
springboot使用redis
springboot使用redis redis-service.exe : 服务端,启动后不要关闭 redis-cli.exe : 客户端,访问redis中的数据 redisclient-win32.x86_64.2.0.jar : redis的图形界面客户端,执行方式是在这个文件的目录执行 java -jar redisclient-win32.x86_64.2.0.jar或者在这个jar包的目录…...
【原创】Open WebUI 本地部署
使用官网的默认部署,遇到不少的问题。比如白屏问题,其实需要修改几个参数即可。 其实在部署的时候有不少参数 WEBUI_AUTH False ENABLE_OPENAI_API 0 PATH /usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin LANG C.UTF-8…...
【实战篇】【深度解析DeepSeek:从机器学习到深度学习的全场景落地指南】
一、机器学习模型:DeepSeek的降维打击 1.1 监督学习与无监督学习的"左右互搏" 监督学习就像学霸刷题——给标注数据(参考答案)训练模型。DeepSeek在信贷风控场景中,用逻辑回归模型分析百万级用户数据,通过特征工程挖掘出"凌晨3点频繁申请贷款"这类魔…...
SpringBoot高校运动会管理系统 附带详细运行指导视频
文章目录 一、项目演示二、项目介绍三、运行截图四、主要代码1.报名赛事代码2.用户登录代码3.保存成绩代码 一、项目演示 项目演示地址: 视频地址 二、项目介绍 项目描述:这是一个基于SpringBoot框架开发的高校运动会管理系统项目。首先,这…...
【Linux网络-HTTP协议】HTTP基础概念+构建HTTP
代码定位:南毅c/Linux - Gitee.com HTTP协议 介绍 虽然我们说,应用层协议是我们程序猿自己定的.但实际上,已经有大佬们定义了一些现成的,又非常好用的应用层协议,供我们直接参考使用。HTTP(超文本传输协议)就是其中之一。 在互联网世界中,…...
web3.0简介
Web3.0(或简称 Web3)是近年来广泛讨论的一个新型互联网概念,其核心思想在于利用区块链及相关分布式技术,打造一个更加开放、去中心化、透明且以用户为主导的网络生态系统。这意味着在 Web3.0 时代,用户不再只是信息的消…...
高频 SQL 50 题(基础版)_626. 换座位
高频 SQL 50 题(基础版)_626. 换座位 select(case when mod(id,2)!0 AND counts ! id then id1when mod(id,2)!0 AND counts id then idelse id -1end) as id,student fromseat,(selectcount(*) as countsfrom seat) as seat_counts order by id asc;...
hive 面试题
Hive基础概念 1.1 Hive是什么? 基于Hadoop的数据仓库工具,支持类SQL(HiveQL)查询,底层转换为MapReduce/Tez/Spark任务。 核心功能:数据ETL、查询、分析;定位:OLAP(分析…...
【Jenkins】个人向-Jenkinsfile如何写
官方参考:https://www.jenkins.io/doc/book/pipeline/syntax/ Pipeline Utility Steps 插件:https://birdbook.com.cn/ops/ci/jenkins/plugins/pipeline%20utility%20steps.html 常用环境变量 含义表达式备注params,传入参数传入参数params…...
python第十一课:并发编程 | 多任务交响乐团
🎯 本节目标 理解多线程/多进程/协程的应用场景掌握threading与multiprocessing核心用法学会使用asyncio进行异步编程开发实战项目:高并发爬虫引擎破解GIL锁的性能迷思 1️⃣ 并发编程三剑客 🎻 生活化比喻: 多线程 → 餐厅多个…...
Android SystemUI深度定制实战:下拉状态栏集成响铃功能开关全解析
一、功能实现全景视图 目标场景:在Android 14系统级ROM定制中,为SystemUI下拉状态栏的QuickQSPanel区域新增响铃模式切换开关,实现静音/响铃快速切换功能。该功能需通过三层关键改造实现: 二、核心实现三部曲 1. 配置注入&…...
基于 Flink CDC YAML 的 MySQL 到 Kafka 流式数据集成
本教程的演示都将在 Flink CDC CLI 中进行,无需一行 Java/Scala 代码,也无需安装 IDE。 这篇教程将展示如何基于 Flink CDC YAML 快速构建 MySQL 到 Kafka 的 Streaming ELT 作业,包含整库同步、表结构变更同步演示和关键参数介绍。 准备阶段…...
ubuntu下r8125网卡重启丢失修复案例一则
刚装的一台服务器,ubuntu24.04,主板网卡是r8125,安装服务后会莫名其妙丢失驱动 按照官网的方法下载最新8125驱动包: Realtek 然后卸载驱动 rmmod r8125 然后在驱动包里安装(幸好我之前装了build-essential&#x…...
解决 ERROR 1130 (HY000): Host is not allowed to connect to this MySQL server
当使用 MySQL 时,您可能会遇到错误信息“ERROR 1130 (HY000): Host ‘hostname’is not allowed to connect to this MySQL server”这是 MySQL 用于防止未经授权的访问的标准安全特性。实际上,服务器还没有配置为接受来自相关主机的连接。 Common Caus…...
科普|无人机专业术语
文章目录 前言一、飞控二、电调三、通道四、2S、3S、4S电池五、电池后面C是什么意思?六、电机的型号七、什么是电机的KV值?八、螺旋桨的型号九、电机与螺旋桨的搭配 前言 无人机飞控系统控制飞行姿态,电调控制电机转速,遥控器通道控制飞行动作。电池C…...
Qt:窗口
目录 菜单栏 QMenuBar 菜单添加快捷键 添加子菜单 添加分割线和添加图标 QMenuBar创建方式 工具栏 QToolBar 和菜单栏搭配 创建多个工具栏 状态栏 QStatusBar 状态栏中添加其他控件 浮动窗口 QDockWidget 对话框 对话框的内存释放问题 自定义对话框界面 模态对话…...
深入浅出 Go 语言:协程(Goroutine)详解
深入浅出 Go 语言:协程(Goroutine)详解 引言 Go 语言的协程(goroutine)是其并发模型的核心特性之一。协程允许你轻松地编写并发代码,而不需要复杂的线程管理和锁机制。通过协程,你可以同时执行多个任务,并…...
Python从0到100(八十九):Resnet、LSTM、Shufflenet、CNN四种网络分析及对比
前言: 零基础学Python:Python从0到100最新最全教程。 想做这件事情很久了,这次我更新了自己所写过的所有博客,汇集成了Python从0到100,共一百节课,帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…...
实验:k8s+keepalived+nginx+iptables
1、创建两个nginx的pod,app都是nginx nginx1 nginx2 2、创建两个的pod的service 3、配置两台keepalived的调度器和nginx七层反向代理,VIP设置192.168.254.110 keepalived调度器master keepalived调度器backup 两台调度器都配置nginx七层反向代理&#…...
elpis全栈课程学习之elpis-core学习总结
elpis全栈课程学习之elpis-core学习总结 核心原理 elpis-core是全栈框架elpis的服务端内核,主要应用于服务端接口的开发以及页面的SSR渲染,elpis-core基于约定优于配置的原理,通过一系列的loader来加载对应的文件,大大节约用户的…...
LlamaFactory-webui:训练大语言模型的入门级教程
LlamaFactory是一个开源框架,支持多种流行的语言模型,及多种微调技术,同时,以友好的交互式界面,简化了大语言模型的学习。 本章内容,从如何拉取,我已经搭建好的Llamafactory镜像开始࿰…...
手机打电话时如何识别对方按下的DTMF按键的字符-安卓AI电话机器人
手机打电话时如何识别对方按下的DTMF按键的字符 --安卓AI电话机器人 一、前言 前面的篇章中,使用蓝牙电话拦截手机通话的声音,并对数据加工,这个功能出来也有一段时间了。前段时间有试用的用户咨询说:有没有办法在手机上ÿ…...
Spring Cloud LoadBalancer详解
一、介绍 Spring Cloud LoadBalancer是Spring Cloud官方自己提供的客户端负载均衡器,抽象和实现,用来替代Ribbon(已经停更), 二、Ribbon和Loadbalance 对比 组件组件提供的负载策略支持负载的客户端Ribbon随机 RandomRule轮询 RoundRobinRule 重试 RetryRule最低并发 Bes…...
使用Spring Boot与达梦数据库(DM)进行多数据源配置及MyBatis Plus集成
使用Spring Boot与达梦数据库(DM)进行多数据源配置及MyBatis Plus集成 在现代企业级应用开发中,处理多个数据源是一个常见的需求。本文将详细介绍如何使用Spring Boot结合达梦数据库(DM),并通过MyBatis Plus来简化数据库操作&…...
