Django的简单通用模型相关数据预取框架,解决您需要为对象获取相关数据时出现的“1+N查询”问题。
项目描述
为Django提供简单通用的模型相关数据预取框架,解决您需要为对象获取相关数据时出现的“1+N查询”问题。
在大多数情况下,您将具有正向关系(指向某物的外键)并可以使用select_related在相同查询中获取该数据。然而,在某些情况下,您不能以这种方式设计您的模型,并需要从反向关系(具有指向您的对象的外键的模型)获取数据。
Django 提供了 prefetch_related 功能,然而,这个框架在编写数据映射和查询函数的代价下,提供了比 Django 的 prefetch_related 查询集方法更大的灵活性。这具有优势,您可以进行 prefetch_related 无法完成的事情(请参阅下方的最新书籍 示例)。
自由软件:BSD 许可证
安装指南
安装它
pip install django-prefetch
将其用作您模型默认的管理器(或者如果您有自定义管理器,则作为基类)。
需求
- 操作系统:
任意
- 运行时:
Python 2.7、3.3+ 或 PyPy
- 包:
Django>=1.9
示例
以下是模型和预取设置的简单示例
from django.db import models from prefetch import PrefetchManager, Prefetcher class Author(models.Model): name = models.CharField(max_length=100) objects = PrefetchManager( books = Prefetcher( filter = lambda ids: Book.objects.filter(author__in=ids), reverse_mapper = lambda book: [book.author_id], decorator = lambda author, books=(): setattr(author, 'books', books) ), latest_book = Prefetcher( filter = lambda ids: Book.objects.filter(author__in=ids), reverse_mapper = lambda book: [book.author_id], decorator = lambda author, books=(): setattr( author, 'latest_book', max(books, key=lambda book: book.created) if books else None ) ) ) class Book(models.Model): class Meta: get_latest_by = 'created' name = models.CharField(max_length=100) created = models.DateTimeField(auto_now_add=True) author = models.ForeignKey(Author)
使用方法如下
for a in Author.objects.prefetch('books', 'latest_book'): print a.books print a.latest_book
预取器参数
示例模型
class LatestNBooks(Prefetcher): def __init__(self, count=2): self.count = count def filter(self, ids): return Book.objects.filter(author__in=ids) def reverse_mapper(self, book): return [book.author_id] def decorator(self, author, books=()): books = sorted(books, key=lambda book: book.created, reverse=True) setattr(author, 'latest_%s_books' % self.count, books[:self.count]) class Author(models.Model): name = models.CharField(max_length=100) objects = PrefetchManager( latest_n_books = LatestNBooks )
使用方法如下
from prefetch import P for a in Author.objects.prefetch(P('latest_n_books', count=5)): print a.latest_5_book
其他示例
查看测试以获取更多示例。
待办事项
记录 Prefetcher 的 collect 选项
创建涵盖自定义 collect 和 mapper 的测试
开发
要运行所有测试,请运行
tox
注意,要组合来自所有 tox 环境的覆盖率数据,请运行
Windows |
set PYTEST_ADDOPTS=--cov-append tox |
---|---|
其他 |
PYTEST_ADDOPTS=--cov-append tox |
变更日志
1.2.3 (2021-06-01)
现在支持主表中任何主键,默认情况下使用映射器,而不仅仅是“id”列。由 Stas Fomin 在 #20 贡献。
1.2.2 (2021-04-11)
添加了对 Django 2.0 的支持
1.2.1 (2018-09-04)
修复了更改日志中缺失的条目。
1.2.0 (2018-09-04)
添加了对 Django 1.11 的支持,删除了对 Django <1.9 的支持。由 Martin Bachwerk 在 #16 贡献。
1.1.0 (2016-02-20)
1.0.1 (2015-09-05)
修复了管理器类型检查。由 George Ma 在 #11 贡献。
1.0.0 (2014-12-05)
修复了使用预取时移除 select_related 的问题(#9)。