【问题标题】:django: select_related with entry_setdjango:select_related 与 entry_set
【发布时间】:2010-11-06 14:39:54
【问题描述】:

entry_set 是否应该与 select_related 一起缓存?即使在我使用 select_related 之后,我的数据库仍然会接到电话。相关部分

class Alias(models.Model):
    achievements = models.ManyToManyField('Achievement', through='Achiever')

    def points(self) :
        points = 0
        for a in self.achiever_set.all() :
            points += a.achievement.points * a.count
        return points

class Achievement(models.Model):
    name = models.CharField(max_length=100)
    points = models.IntegerField(default=1)

class Achiever(models.Model):
    achievement = models.ForeignKey(Achievement)
    alias = models.ForeignKey(Alias)
    count = models.IntegerField(default=1)

aliases = Alias.objects.all().select_related()
for alias in aliases :
    print "points : %s" % alias.points()
    for a in alias.achiever_set.all()[:5] :
        print "%s x %d" % (a.achievement.name, a.count)

我在开始时看到一个大的连接查询,然后每个成就都单独调用。用于点数和名称查找。

这是一个错误,还是我做错了什么?

【问题讨论】:

    标签: django django-models django-select-related


    【解决方案1】:

    在 Django 1.4 中,您可以使用 prefetch_related 来处理多对多关系:

    https://docs.djangoproject.com/en/dev/ref/models/querysets/#prefetch-related

    【讨论】:

      【解决方案2】:

      在 Django 1.3 中,您可以使用 Queryset.values() 并执行以下操作:

      Alias.objects[.filter().exclude() etc.].values('achievements__name', 'achievement__points')
      

      只有 drwaback 是你得到 QuerySetList 而不是 QuerySet。但这可以通过将所有必要的字段传递给 values() 来简单地克服 - 你必须改变你的看法;)

      这可以为您节省少量查询...

      详细信息可以在 django 文档中找到: http://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.values

      【讨论】:

        【解决方案3】:

        Select_related() 不适用于多字段。目前,这还没有计划,但可能是未来的功能。见http://code.djangoproject.com/ticket/6432

        在这种情况下,如果您想进行单个查询,您有两个选项 1)制作自己的SQL,可能不会漂亮或快速。 2)您也可以使用外键查询模型。在这种情况下,您将能够使用 select_related。您仍然无法访问 modelname_set,但通过一些格式,您将能够在单个查询中审查您需要的数据。没有一个选项是理想的,但你也可以让它以相当不错的速度工作。

        【讨论】:

        • 无赖。你会如何建议我做那个查询?手动 SQL?
        • 对于任何阅读的人,M2M 和反向 FK 的 select_related() 等效项是 prefetch_related(),并在 1.4 中添加。
        猜你喜欢
        • 2010-11-26
        • 1970-01-01
        • 2011-02-25
        • 1970-01-01
        • 1970-01-01
        • 2012-02-03
        • 2018-02-22
        • 2015-03-01
        • 2016-03-23
        相关资源
        最近更新 更多