django之select_related 与 prefetch_related用法

devtools/2024/9/24 3:48:11/

在 Django 中,select_relatedprefetch_related 是用于优化查询的两个重要方法。它们通过减少数据库查询次数来提高性能,但它们的工作方式有所不同。

select_related

select_related 使用 SQL 的 JOIN 操作来获取相关对象。它适用于一对一和多对一的关系(如 ForeignKey 和 OneToOneField)。它会在单个查询中获取相关对象的数据,从而减少数据库查询次数。

示例

假设我们有以下模型:

python">from django.db import modelsclass Author(models.Model):name = models.CharField(max_length=100)email = models.EmailField()def __str__(self):return self.nameclass Book(models.Model):title = models.CharField(max_length=200)publication_date = models.DateField()author = models.ForeignKey(Author, related_name='books', on_delete=models.CASCADE)def __str__(self):return self.title

可以使用 select_related 来优化查询:

python"># 获取所有书籍及其对应的作者
books = Book.objects.select_related('author').all()for book in books:print(f"{book.title} by {book.author.name}")

在这个示例中,select_related('author') 会在单个查询中获取所有书籍及其对应的作者,从而避免了每次访问 book.author 时的额外查询。

prefetch_related

prefetch_related 使用单独的查询来获取相关对象,然后在 Python 中进行关联。它适用于一对多和多对多的关系(如 ForeignKey、OneToOneField 和 ManyToManyField)。它会在单独的查询中获取相关对象的数据,然后在内存中进行关联。

示例

假设我们有以下模型:

python">from django.db import modelsclass Author(models.Model):name = models.CharField(max_length=100)email = models.EmailField()def __str__(self):return self.nameclass Book(models.Model):title = models.CharField(max_length=200)publication_date = models.DateField()author = models.ForeignKey(Author, related_name='books', on_delete=models.CASCADE)def __str__(self):return self.title

可以使用 prefetch_related 来优化查询:

python"># 获取所有作者及其对应的书籍
authors = Author.objects.prefetch_related('books').all()for author in authors:print(f"Books by {author.name}:")for book in author.books.all():print(f" - {book.title}")

在这个示例中,prefetch_related('books') 会在单独的查询中获取所有作者及其对应的书籍,然后在内存中进行关联,从而避免了每次访问 author.books.all() 时的额外查询。

选择 select_related 还是 prefetch_related

  • select_related适用于一对一和多对一的关系。它使用 SQL JOIN 操作,在单个查询中获取相关对象的数据。
  • prefetch_related适用于一对多和多对多的关系。它使用单独的查询来获取相关对象的数据,然后在内存中进行关联。

组合使用

在某些情况下,可能需要同时使用 select_relatedprefetch_related 来优化查询。

示例

假设我们有以下模型:

python">from django.db import modelsclass Publisher(models.Model):name = models.CharField(max_length=100)def __str__(self):return self.nameclass Author(models.Model):name = models.CharField(max_length=100)email = models.EmailField()publisher = models.ForeignKey(Publisher, related_name='authors', on_delete=models.CASCADE)def __str__(self):return self.nameclass Book(models.Model):title = models.CharField(max_length=200)publication_date = models.DateField()author = models.ForeignKey(Author, related_name='books', on_delete=models.CASCADE)def __str__(self):return self.title

可以同时使用 select_relatedprefetch_related 来优化查询:

python"># 获取所有书籍及其对应的作者和出版社
books = Book.objects.select_related('author__publisher').prefetch_related('author__books').all()for book in books:print(f"{book.title} by {book.author.name} (Publisher: {book.author.publisher.name})")print("Other books by this author:")for other_book in book.author.books.all():if other_book != book:print(f" - {other_book.title}")

在这个示例中,select_related('author__publisher') 会在单个查询中获取书籍、作者及其对应的出版社,而 prefetch_related('author__books') 会在单独的查询中获取作者及其对应的书籍,然后在内存中进行关联。


http://www.ppmy.cn/devtools/96039.html

相关文章

[Meachines] [Medium] solidstate Apache JAMES RCE+POP3邮件泄露+定时任务权限提升

信息收集 IP AddressOpening Ports10.10.10.51TCP:22,25,80,110,119,4555 $ nmap -p- 10.10.10.51 --min-rate 1000 -sC -sV PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.4p1 Debian 10deb9u…

C语言 | Leetcode C语言题解之第345题反转字符串中的元音字母

题目&#xff1a; 题解&#xff1a; char vowel[] "aeiouAEIOU";bool isVowel(char ch) {for (int i 0; vowel[i]; i) {if (vowel[i] ch) {return true;}}return false; };char* reverseVowels(char* s) {int n strlen(s);int i 0, j n - 1;while (i < j) …

【Docker】如何更简单的做一个dockerfile文件?

一&#xff0c;介绍 Dockerfile 是用来定义 Docker 镜像构建过程的文本文件。它包含了一系列的指令和参数&#xff0c;告诉 Docker 如何组装一个镜像。一个基本的 Dockerfile 通常包含以下几个部分&#xff1a; 1.基础镜像指令&#xff08;FROM&#xff09;&#xff1a; 指定…

MongoDB 在 Java 中的使用教程

目录 MongoDB 简介环境准备使用 Java 连接 MongoDB基本 CRUD 操作复杂查询操作索引和性能优化事务管理总结 1. MongoDB 简介 MongoDB 是一个基于分布式文件存储的 NoSQL 数据库系统。它以文档&#xff08;JSON 形式&#xff09;存储数据&#xff0c;具有高扩展性和灵活的数据…

免费的抓包软件wireshark以及简单使用

官网下载链接 https://www.wireshark.org/download.html 安装成功后直接打开即可使用 点击‘wan’即可使用 抓包信息可以在底部菜单栏查看 过滤之查看‘tcp’类型的&#xff0c;自行输入过滤

【问题解决3】【已解决】Cannot determine path to‘tools.jar‘libraryfor17

前几天在IDEA运行JAVA项目时&#xff0c;出现这个报错。 这是因为是这个笔记本上安装的IDEA版本是“IntelliJ IDEA 2020.3.1”&#xff0c;与JDK17版本不兼容&#xff0c;这种情况下要想使得IDEA版本与JDK版本兼容&#xff0c;就需要升级IDEA版本或者使用JDK较低版本&#xff…

只有IP如何实现https访问

IP也是访问网站的一种方式&#xff0c;现在有很多网站并未绑定域名&#xff0c;而是通过IP直接访问的。 但是域名访问网站的方式会更多一些&#xff0c;主要还是因为域名相较于IP数字要更加好记&#xff0c;所以域名绑定网站的情况会更多。 随着现在网络安全意识的逐渐提升&a…

基于CDIO概念的人工智能物联网系统开发与实施的人才培养研究

目录 1. 引言&#xff08;Introduction&#xff09; 2. AIoT技术及其培训特点&#xff08;The Characteristics of AIOT and Its Training&#xff09; 3. 基于CDIO概念的AIoT课程改革&#xff08;CDIO Concept-based Reform of AIOT Course&#xff09; 4. AIoT课程内容安…