django - annotate()而不是distinct()

时间:2013-08-10 08:00:38

标签: python django django-queryset

我陷入了这个问题:

我有两种模式:

位置和费率。

每个位置都有其费率,可能是多种费率。

我希望按照其费率按顺序排列。

显然,order_bydistinct()不能一起工作:

locations = Location.objects.filter(**s_kwargs).order_by('locations_rate__rate').distinct('id')

然后我阅读了文档并来到了annotate()。但我不确定是否必须在注释之间使用函数。

如果我这样做:

locations = Location.objects.filter(**s_kwargs).annotate(rate=Count('locations_rate__rate')).order_by('rate')

但这会计算费率和订单总和。我想获得按照这些费率的价格订购费率的地点。

我的模型定义是:

class Location(models.Model):
  name = models.TextField()
  adres = models.TextField()

class Rate(models.Model):
  location = models.ForeignKey(Location,related_name='locations_rate')
  rate = models.IntegerField(max_length=2)
  price_rate = models.IntegerField(max_length=2) #<--- added now
  datum = models.DateTimeField(auto_now_add=True,blank=True) #<--- added now

4 个答案:

答案 0 :(得分:1)

试试这个:

from django.db.models import Count, Sum
# if you want to annotate by count of rates
locations = Location.objects.filter(**s_kwargs) \
    .annotate(rate_count = Count('locations_rate')) \
    .order_by('rate_count')

# if you want to annotate on values of rate e.g. Sum
locations = Location.objects.filter(**s_kwargs) \
    .annotate(rate_count = Sum('locations_rate')) \
    .order_by('rate_count')

答案 1 :(得分:1)

annotate(* args,** kwargs),使用提供的聚合值列表(平均值,总和等)来注释QuerySet中的每个对象 已经在与QuerySet中的对象相关的对象上计算。

因此,如果您只想获得按其费率排序的地点,那么您不必使用注释()

     you can try this :

     loc = Location.objects.all()
     rate = Rate.objects.filter(loc=rate__location).order_by('-rate')

答案 2 :(得分:1)

问题不在于如何在Django中查询您描述的问题。这是你的问题不正确或没有财产思考。让我用一个例子来解释:

假设您有两个Location个对象,l1l2l1有两个Rate个与之关联的对象,r1r3r1.rate = 1r3.rate = 3;并且l2有一个与其相关的费率对象r2,例如r2.rate = 2。现在,您的查询结果l1跟随l2l2后跟l1的顺序应该是多少?其中一个l1的费率低于l2,另一个的费率高于l2

答案 3 :(得分:1)

可能你想要这样的东西:

locations = (Location.objects.filter(**s_kwargs)
             .values('locations_rate__rate')
             .annotate(Count('locations_rate__rate'))
             .order_by('locations_rate__rate'))

您需要Count(),因为您确实需要GROUP BY个查询,而GROUP BY仅适用于COUNTSUM等汇总功能。

无论如何,我认为您的问题可以通过正常distinct()来解决:

locations = (Location.objects.filter(**s_kwargs)
             .order_by('locations_rate__rate')
             .distinct('locations_rate__rate'))

为什么要使用annotate()

我没有测试过两者,但希望它有所帮助。