是否应使用select_related缓存entry_set?即使我使用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)
我在开始时看到一个很大的联接查询,然后个人调用每个成就。点数和名称查找。
这是一个错误,还是我做错了什么?
答案 0 :(得分:4)
Select_related()不适用于manytomanyfields。目前,这是未计划的,但可能是未来的功能。见http://code.djangoproject.com/ticket/6432
在这种情况下,如果您想进行单个查询,则有两个选项 1)制作自己的SQL,可能不会很漂亮或很快。 2)您还可以使用foreignkey查询模型。在这种情况下,您可以使用select_related。您将无法访问modelname_set,但通过某种格式化,您可以在单个查询中审核所需的数据。没有一个选项是理想的,但你可以让它以相反的速度工作。
答案 1 :(得分:4)
使用Django 1.4,您可以使用prefetch_related,它将适用于ManyToMany关系:
https://docs.djangoproject.com/en/dev/ref/models/querysets/#prefetch-related
答案 2 :(得分:0)
在Django 1.3中您可以使用Queryset.values()并执行以下操作:
Alias.objects[.filter().exclude() etc.].values('achievements__name', 'achievement__points')
只有drwaback是你获得QuerySetList而不是QuerySet。但是这可以通过将所有必要的字段传递给值()来简单地克服 - 你必须改变你的看法;)
这可以为您节省少量查询...
详细信息可以在django docs中找到: http://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.values