django之select_related 与 prefetch_related用法

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

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

示例

假设我们有以下模型:

python 复制代码
from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField()

    def __str__(self):
        return self.name

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

示例

假设我们有以下模型:

python 复制代码
from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField()

    def __str__(self):
        return self.name

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

组合使用

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

示例

假设我们有以下模型:

python 复制代码
from django.db import models

class Publisher(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class 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.name

class 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') 会在单独的查询中获取作者及其对应的书籍,然后在内存中进行关联。

相关推荐
C嘎嘎嵌入式开发2 小时前
(2)100天python从入门到拿捏
开发语言·python
Stanford_11063 小时前
如何利用Python进行数据分析与可视化的具体操作指南
开发语言·c++·python·微信小程序·微信公众平台·twitter·微信开放平台
white-persist4 小时前
Python实例方法与Python类的构造方法全解析
开发语言·前端·python·原型模式
Java 码农4 小时前
Centos7 maven 安装
java·python·centos·maven
倔强青铜三5 小时前
苦练Python第63天:零基础玩转TOML配置读写,tomllib模块实战
人工智能·python·面试
浔川python社6 小时前
《网络爬虫技术规范与应用指南系列》(xc—3):合规实操与场景落地
python
B站计算机毕业设计之家6 小时前
智慧交通项目:Python+YOLOv8 实时交通标志系统 深度学习实战(TT100K+PySide6 源码+文档)✅
人工智能·python·深度学习·yolo·计算机视觉·智慧交通·交通标志
IT森林里的程序猿6 小时前
基于机器学习方法的网球比赛胜负趋势预测
python·机器学习·django
正牌强哥6 小时前
Futures_ML——机器学习在期货量化交易中的应用与实践
人工智能·python·机器学习·ai·交易·akshare
倔强青铜三6 小时前
苦练Python第62天:零基础玩转CSV文件读写,csv模块实战
人工智能·python·面试