反向关系中的Django聚合

时间:2010-05-04 15:11:10

标签: django orm annotations

鉴于这两个模型:

class Profile(models.Model):
    user = models.ForeignKey(User, unique=True, verbose_name=_('user'))
    about = models.TextField(_('about'), blank=True)
    zip = models.CharField(max_length=10, verbose_name='zip code', blank=True)
    website = models.URLField(_('website'), blank=True, verify_exists=False)

class ProfileView(models.Model):
    profile = models.ForeignKey(Profile)
    viewer = models.ForeignKey(User, blank=True, null=True)
    created = models.DateTimeField(auto_now_add=True)

我想让所有个人资料按总观看次数排序。我可以获得一个按总视图排序的配置文件ID列表:

ProfileView.objects.values('profile').annotate(Count('profile')).order_by('-profile__count')

但这只是一个配置文件ID的字典,这意味着我必须循环它并将一个配置文件对象列表放在一起。这是一些额外的查询,仍然不会导致QuerySet。那时,我不妨放弃原始SQL。在我这样做之前,有没有办法从Profile模型中做到这一点? ProfileViews通过ForeignKey字段相关,但它不像Profile模型那样知道,所以我不确定如何将两者结合在一起。

顺便说一句,我意识到我可以将视图作为属性存储在Profile模型上,这可能就是我在这里所做的,但我仍然有兴趣学习如何更好地使用聚合函数。 / p>

2 个答案:

答案 0 :(得分:10)

  

ProfileViews通过ForeignKey字段相关,但它不像Profile模型那样知道

Profile模型确实知道这一点。 您应该可以执行以下操作:

  Profile.objects.all().annotate(count_views=Count('profileview__pk')).order_by('count_views')

修改:在这里,您可以找到有关跨越关系http://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships

的查找的Django文档

答案 1 :(得分:4)

肯定会有效:

Profile.objects.all().annotate(viewcount=Count('profileview')).order_by('-viewcount')

正如Botondus所说,Profile模型知道向后的ForeignKey关系。