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 优化性能。

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

touchgfx的工作机制

touchgfx的工作机制 一.MVP软件架构 MVP的全称为Model-View-Presenter Model: 就是数据部分,在整个touchgfx应用中,只有一个Model类实例对象,它为所有的Screen屏幕界面服务,可以理解成是一个全局变量区,同时它还负责和后端系统通信 View: 就是UI界面部分,对应于View类,在整…

网站搭建wp

前置准备工作 需要下载Git,note.js,在官网上可以搜索并安装 搭建过程 这里借助hexo工具 1. 本地博客搭建 首先创建本地文件夹,并在该文件夹里面创建一个叫做hexo的文件夹在该文件夹中选择Git Bash 进入hexo官网将五条指令用bash运行运行…

现场可以通过手机或者pad实时拍照上传到大屏幕的照片墙现场大屏电子照片墙功能

现场可以通过手机或者pad实时拍照上传到大屏幕的照片墙现场大屏电子照片墙功能,每个人都可以通过手机实时拍照上传到大屏幕上,同时还可以发布留言内容,屏幕上会同步滚动播放展示所有人的照片和留言。相比校传统的照片直播功能更加灵活方便,而…

MySQL 主从复制原理及其工作过程

一、MySQL主从复制原理 MySQL 主从复制是一种将数据从一个 MySQL 数据库服务器(主服务器,Master)复制到一个或多个 MySQL 数据库服务器(从服务器,Slave)的技术。以下简述其原理,主要包含三个核…

【蓝桥杯单片机】第十三届省赛第二场

一、真题 二、模块构建 1.编写初始化函数(init.c) void Cls_Peripheral(void); 关闭led led对应的锁存器由Y4C控制关闭蜂鸣器和继电器 2.编写LED函数(led.c) void Led_Disp(unsigned char ucLed); 将ucLed取反的值赋给P0 开启锁存器 关闭锁存…

Android Coil3缩略图、默认占位图placeholder、error加载错误显示,Kotlin(3)

Android Coil3缩略图、默认占位图placeholder、error加载错误显示,Kotlin(3) Android Coil3缩略图、默认占位图placeholder、error加载错误显示,Kotlin(1)-CSDN博客文章浏览阅读667次,点赞18次&…

MariaDB 历史版本下载地址 —— 筑梦之路

MariaDB 官方yum源里面只有目前在维护的版本,而有时候对于老项目来说还是需要老版本的rpm包,国内很多镜像站都是同步的官方仓库,因此下载老版本也不好找,这里主要记录下从哪里可以下载到历史版本的MariaDB rpm包。 1. 官方归档网…

RoCBert:具有多模态对比预训练的健壮中文BERT

摘要 大规模预训练语言模型在自然语言处理(NLP)任务上取得了最新的最优结果(SOTA)。然而,这些模型容易受到对抗攻击的影响,尤其是对于表意文字语言(如中文)。 在本研究中&#xff0…

20250212:https通信

1:防止DNS劫持:使用 https 进行通信。 因为是SDK授权开发,需要尽量压缩so库文件和三方依赖。所以第一想法是使用 head only 的 cpp-httplib 进行开发。 cpp-httplib 需要 SSL 版本是 3.0及以上。但本地已经在开发使用的是1.0.2a版本,不满足需求。 方案1:升级OpenSSL 将Op…

数据驱动未来!天合光能与永洪科技携手开启数字化新篇章

在信息化时代的今天,企业间的竞争早就超越了传统产品与服务的范畴,新的核心竞争力即——数据处理能力和信息技术的应用。作为数据技术领域的领军者,永洪科技凭借其深厚的技术积累和丰富的行业经验,成功助力天合光能实现数字化升级…

Android之图片保存相册及分享图片

文章目录 前言一、效果图二、实现步骤1.引入依赖库2.二维码生成3.布局转图片保存或者分享 总结 前言 其实现在很多分享都是我们自定义的,更多的是在界面加了很多东西,然后把整个界面转成图片保存相册和分享,而且现在分享都不需要第三方&…

政安晨的AI大模型训练实践 十一 - 基于千问的Qwen2.5-VL-3B-Instruct 多模态模型进行微调参数认知 2

政安晨的个人主页:政安晨 欢迎 👍点赞✍评论⭐收藏 希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正! 微调一个大模型要准备的背景知识还是很多的。 本节我们介绍训练阶段的一些主要参数。 这是训…

心理咨询小程序的未来发展

还在眼巴巴看着心理咨询行业的巨大蛋糕却无从下口?今天就来聊聊心理咨询小程序的无限潜力 据统计,全球超 10 亿人受精神心理问题困扰,国内心理健康问题也日益突出,心理咨询需求猛增。可传统心理咨询预约难,费用高&…

反欺诈平台|基于Springboot+vue的反欺诈平台(源码+数据库+文档)​

目录 基于Springbootvue的反欺诈平台系统 一、前言 二、系统设计 三、系统功能设计 5.1用户信息管理 5.2 反诈视频管理 5.3视频收藏管理 5.1案例分析管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介…

P8772 [蓝桥杯 2022 省 A] 求和--简单题的陷阱——(不开long long见祖宗!!!

P8772 [蓝桥杯 2022 省 A] 求和 题目分析代码 题目 分析 cnmmd 没什么好分析的&#xff0c;n≤210^5&#xff0c;tmd 我拿着a[100010]算半天 简单题的陷阱- - 代码 #include <iostream> #include <vector> #include <string> #include <algorithm> #i…

如何让传统制造企业从0到1实现数字化突破?

随着全球制造业不断向智能化、数字化转型&#xff0c;传统制造企业面临着前所未有的机遇与挑战。数字化转型不仅是技术的革新&#xff0c;更是管理、文化、业务流程等全方位的变革。从零开始&#xff0c;如何带领一家传统制造企业走向数字化突破&#xff0c;是许多企业领导者面…

TMDS视频编解码算法

因为使用的是DDR进行传输&#xff0c;即双倍频率采样&#xff0c;故时钟只用是并行数据数据的5倍&#xff0c;而不是10倍。 TMDS算法流程&#xff1a; 视频编码TMDS算法流程实现&#xff1a; timescale 1 ps / 1ps //DVI编码通常用于视频传输&#xff0c;将并行数据转换为适合…

SpringBoot源码解析(十一):准备应用上下文

SpringBoot源码系列文章 SpringBoot源码解析(一)&#xff1a;SpringApplication构造方法 SpringBoot源码解析(二)&#xff1a;引导上下文DefaultBootstrapContext SpringBoot源码解析(三)&#xff1a;启动开始阶段 SpringBoot源码解析(四)&#xff1a;解析应用参数args Sp…

跟李沐学AI:InstructGPT论文精读(SFT、RLHF)

原论文&#xff1a;[2203.02155] Training language models to follow instructions with human feedback 原视频&#xff1a;InstructGPT 论文精读【论文精读48】_哔哩哔哩_bilibili 简介 1. RLHF 的基本概念 RLHF 是一种结合强化学习和人类反馈的训练方法&#xff0c;旨在…

基于YOLO11深度学习的运动鞋品牌检测与识别系统【python源码+Pyqt5界面+数据集+训练代码】

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…