当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Python Django QuerySet.defer用法及代码示例


本文介绍 django.db.models.query.QuerySet.defer 的用法。

声明

defer(*fields)

在一些复杂的 data-modeling 情况下,您的模型可能包含很多字段,其中一些可能包含大量数据(例如,文本字段),或者需要进行昂贵的处理才能将它们转换为 Python 对象。如果您在某些情况下使用查询集的结果,当您最初获取数据时不知道是否需要这些特定字段,您可以告诉 Django 不要从数据库中检索它们。

这是通过将字段名称传递给不加载到 defer() 来完成的:

Entry.objects.defer("headline", "body")

具有延迟字段的查询集仍将返回模型实例。如果您访问该字段(一次一个,而不是一次访问所有延迟字段),将从数据库中检索每个延迟字段。

您可以多次调用 defer() 。每次调用都会将新字段添加到延迟集:

# Defers both the body and headline fields.
Entry.objects.defer("body").filter(rating=5).defer("headline")

将字段添加到延迟集中的顺序无关紧要。使用已延迟的字段名称调用 defer() 是无害的(该字段仍将被延迟)。

您可以通过使用标准 double-underscore 表示法来分隔相关字段来延迟加载相关模型中的字段(如果相关模型通过 select_related() 加载):

Blog.objects.select_related().defer("entry__headline", "entry__body")

如果要清除延迟字段集,请将 None 作为参数传递给 defer()

# Load all fields immediately.
my_queryset.defer(None)

模型中的某些字段不会被延迟,即使您要求它们。您永远不能推迟加载主键。如果您使用 select_related() 检索相关模型,则不应延迟加载从主模型连接到相关模型的字段,这样做会导致错误。

注意

defer() 方法(及其表亲, only() ,如下)仅适用于高级 use-cases。当您仔细分析查询并了解exactly 您需要什么信息并衡量返回所需字段与模型的完整字段集之间的差异时,它们提供了优化。

即使您认为自己处于高级用例情况,也只能在无法在查询集加载时确定是否需要额外字段时才使用 defer()。如果您经常加载和使用数据的特定子集,您可以做出的最佳选择是将模型标准化并将未加载的数据放入单独的模型(和数据库表)中。如果列 must 出于某种原因保留在一个表中,请创建一个带有 Meta.managed = False 的模型(请参阅 managed attribute 文档),其中仅包含您通常需要加载的字段并在您可能调用 defer() 的地方使用这些字段.这使您的代码对读者更加明确,速度稍快,并且在 Python 进程中消耗的内存更少。

例如,这两种模型都使用相同的底层数据库表:

class CommonlyUsedModel(models.Model):
    f1 = models.CharField(max_length=10)

    class Meta:
        managed = False
        db_table = 'app_largetable'

class ManagedModel(models.Model):
    f1 = models.CharField(max_length=10)
    f2 = models.CharField(max_length=10)

    class Meta:
        db_table = 'app_largetable'

# Two equivalent QuerySets:
CommonlyUsedModel.objects.all()
ManagedModel.objects.all().defer('f2')

如果非托管模型中需要复制许多字段,最好创建一个具有共享字段的抽象模型,然后让非托管和托管模型从抽象模型继承。

注意

为具有延迟字段的实例调用 save() 时,只会保存加载的字段。有关详细信息,请参阅 save()

相关用法


注:本文由纯净天空筛选整理自djangoproject.com大神的英文原创作品 django.db.models.query.QuerySet.defer。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。