Django ORM 的常用字段类型、外键关联的跨表引用技巧,以及 `_` 和 `__` 的使用场景


一、Django ORM 常用字段类型

1. 基础字段类型
字段类型说明示例
CharField字符串字段,必须指定 max_lengthname = 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 库支持 ImageFieldavatar = 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"))

四、总结

核心技巧
  1. 字段类型选择

    • 根据数据类型选择合适字段(如 CharField vs TextField)。
    • 关联字段注意 on_deleterelated_name 的设置。
  2. 跨表查询

    • 正向查询:直接通过外键字段访问关联对象。
    • 反向查询:使用 related_name 或默认的 模型名_set
    • 复杂查询:通过 __ 跨表连接字段。
  3. _ 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 穿透到 Bookcategory 字段。
  • 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_relatedprefetch_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_relatedselect_related 优化性能。

通过反向查询,你可以轻松实现从“一”对“多”或“多对多”关系的反向导航,让数据关联操作更加灵活高效!

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

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

相关文章

java递归求自然数列的前n项和

概述 实现 /*** 数列 1 2 3 ... n ...* 递归求数列的前n项和* param n* return*/private static long calSum(long n){if (n1) return 1;else {return ncalSum(n-1); // 前n项的和 即第n项的值前n-1项的和}}测试用例 public static void main(String[] args) {long res1 cal…

【Golang 面试题】每日 3 题(六十五)

✍个人博客:Pandaconda-CSDN博客 📣专栏地址:http://t.csdnimg.cn/UWz06 📚专栏简介:在这个专栏中,我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞👍收藏…

16、Python面试题解析:python中的浅拷贝和深拷贝

在 Python 中,浅拷贝(Shallow Copy) 和 深拷贝(Deep Copy) 是处理对象复制的两种重要机制,它们的区别主要体现在对嵌套对象的处理方式上。以下是详细解析: 1. 浅拷贝(Shallow Copy&a…

【Godot4.3】题目与答案解析合并器

免责申明 本文和工具截图中涉及题库和题目,均为本人自学使用,并未有商业和传播企图。如有侵害,联系删改。 概述 笔者本人医学专业从业人员,编程只是业余爱好。在自己的专业应考学习过程当中: 有时候不太喜欢纸质题库…

Lm studio本地部署DeepSeek

为什么用Lm studio Ollama官网下载过慢或失败(Lm默认下载源无法下载,但可以更换下载源)Ollama默认安装至C盘一部分Nivida显卡无法吃满显存资源一部分AMD显卡替换rocm文件后无法启动 Lm studio安装 官网下载:LM Studio - Discov…

基于Qlearning强化学习的2DoF机械臂运动控制系统matlab仿真

目录 1.算法仿真效果 2.算法涉及理论知识概要 2.1 2DoF机械臂运动学模型 2.2 Q-learning强化学习算法原理 3.MATLAB核心程序 4.完整算法代码文件获得 1.算法仿真效果 matlab2022a仿真结果如下(完整代码运行后无水印): 仿真操作步骤可参…

Unity贴图与模型相关知识

一、贴图 1.贴图的类型与形状 贴图类型 贴图形状 2.在Unity中可使用一张普通贴图来生成对应的法线贴图(但并不规范) 复制一张该贴图将复制后的贴图类型改为Normal Map 3.贴图的sRGB与Alpha sRGB:勾选此选项代表此贴图存储于Gamma空间中…

快速上手 Unstructured:安装、Docker部署及PDF文档解析示例

1. 核心概念 1.1 Unstructured简介 Unstructured 是一个强大的 Python 库,专注于从非结构化数据中提取和预处理文本信息,广泛应用于 PDF、Word 文档、HTML 等多种格式的文件处理。其核心功能包括分区、清理、暂存和分块,能够将复杂的非结构化文档转换为结构化输出,为后续…

pyecharts介绍

文章目录 介绍安装pyecharts基本使用全局配置选项 折线图相关配置地图模块使用柱状图使用 介绍 echarts虑是个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可,而Pyhon是门富有表达力的语言&a…

Fisher信息矩阵与Hessian矩阵:区别与联系全解析

Fisher信息矩阵与Hessian矩阵:区别与联系全解析 在统计学和机器学习中,Fisher信息矩阵(FIM)和Hessian矩阵是两个经常出现的概念,它们都与“二阶信息”有关,常用来描述函数的曲率或参数的敏感性。你可能听说…

python与C系列语言的差异总结(1)

/ 表示浮点除法 // 表示整数除法 print(8/3)print(8//3)布尔型 False/True 首字母大写 整数的大小是没有限制的,会根据需要自动增长,仅受限于可用内存的大小。 m**n表示m的n次方 x 4.3 ** 2.4print(x)print(3.5e30 * 2.77e45)print(1000000001.0 *…

Python selenium 库

Selenium 是一个用于自动化 Web 浏览器操作的强大工具,广泛应用于 Web 应用程序测试、网页数据抓取和任务自动化等场景。 Selenium 为各种编程语言提供了 API,用作测试。 目前的官方 API 文档有 C#、JavaScript、Java、Python、Ruby。 安装 Selenium 和…

vllm部署LLM(qwen2.5,llama,deepseek)

目录 环境 qwen2.5-1.5b-instruct 模型下载 vllm 安装 验证安装 vllm 启动 查看当前模型列表 OpenAI Completions API(文本生成) OpenAI Chat Completions API(chat 对话) vllm 进程查看,kill llama3 deep…

Python NumPy库使用指南:从入门到精通

1. 引言 NumPy(Numerical Python)是 Python 中用于科学计算的核心库之一。它提供了强大的多维数组对象(ndarray),以及一系列高效的数学函数,能够轻松处理大规模的数值数据。NumPy 是许多其他科学计算库(如 Pandas、Matplotlib、Scikit-learn 等)的基础。 本文将详细介…

15.2 智能销售顾问系统技术架构解密:构建企业级知识驱动型对话引擎

智能销售顾问系统技术架构解密:构建企业级知识驱动型对话引擎 关键词:RAG 架构设计、销售知识库系统、LoRA 微调优化、多模态交互引擎、高并发服务部署 1. 系统技术架构全景解析 1.1 核心架构设计图 #mermaid-svg-UBkTgaR5lf5WfGMa {font-family:"trebuchet ms",…

用PyTorch从零构建 DeepSeek R1:模型架构和分步训练详解

DeepSeek R1 的完整训练流程核心在于,在其基础模型 DeepSeek V3 之上,运用了多种强化学习策略。 本文将从一个可本地运行的基础模型起步,并参照其技术报告,完全从零开始构建 DeepSeek R1,理论结合实践,逐步…

爬虫基础入门之爬取豆瓣电影Top250-Re正则的使用

网址:豆瓣电影 Top 250 本案例所需要的模块 requests (用于发送HTTP请求)re (用于字符串匹配和操作) 确定需要爬取的数据 : 电影的名称电影的年份电影的评分电影评论人数 一. 发送请求 模拟浏览器向服务器发送请求 准备工作 -分析页面: F12 or 右击点击检查 查看…

力扣hot100——岛屿数量 岛屿问题经典dfs总结

给你一个由 1(陆地)和 0(水)组成的的二维网格,请你计算网格中岛屿的数量。 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 此外,你可以假设该网格的四条边…

FPGA DSP:Vivado 中带有 DDS 的 FIR 滤波器

本文使用 DDS 生成三个信号,并在 Vivado 中实现低通滤波器。低通滤波器将滤除相关信号。 介绍 用DDS生成三个信号,并在Vivado中实现低通滤波器。低通滤波器将滤除较快的信号。 本文分为几个主要部分: 信号生成:展示如何使用DDS&am…

MessageAuthenticator

MessageAuthenticator https://coova.github.io/JRadius/ https://coova.github.io/JRadius/ import org.tinyradius.packet.RadiusPacket; import org.tinyradius.util.RadiusUtil; import java.nio.charset.StandardCharsets;public class RadiusAuthUtils {/*** 生成 RADI…