Django QuerySet:按特定字段限制结果分组
我搜索了一下,没找到办法来实现以下需求:
假设我们有一个Django模型,里面有“field_a”和“field_b”这两个字段。我想限制结果的方式是,对于“field_a”的每一个不同值,最多从模型表中获取N条记录。所以,这不是简单地切片查询集,因为那样无法区分“field_a”的值。
附注:用SQL可以做到这一点。
我们来举个例子:
class ExampleModel(models.Model):
foreign = models.ForeignKey(ForeignTable)
user = models.ForeignKey(User, related_name="user_attending")
基本上,我想做的是:
找到所有具有特定foreign_id
和user_id
的ExampleModels
。但我只想从一组user_id
中找到最多3个user_id
。所以即使有20个匹配的user_id
对应某个foreign_id
,我也只想要前面三个。
谢谢大家的帮助!
编辑:
似乎我的问题被误解了,所以我会提供一个例子。从:
foreign_id=1,user_id=1
foreign_id=1,user_id=2
foreign_id=1,user_id=3
foreign_id=1,user_id=4
foreign_id=2,user_id=5
foreign_id=2,user_id=6
foreign_id=2,user_id=3
foreign_id=2,user_id=2
foreign_id=3,user_id=1
foreign_id=3,user_id=9
结果将是,只有一个查询集:
foreign_id=1,user_id=1
foreign_id=1,user_id=2
foreign_id=1,user_id=3
foreign_id=2,user_id=5
foreign_id=2,user_id=6
foreign_id=2,user_id=3
foreign_id=3,user_id=1
foreign_id=3,user_id=9
3 个回答
0
好吧,你可以试试这样做,针对下面这个模型:
class ExampleModel(models.Model):
foreign = models.ForeignKey(ForeignTable)
user = models.ForeignKey(User, related_name="user_attending")
time_created= models.DateTimeField(auto_now_add=True)
results= ExampleModel.objects.filter(foreign__id=1).annotate(time_created_max=Max('time_created')).order_by('time_created_max').distinct()
three_results= results[:3]
注意:把 order_by
和 distinct
一起用可能会出现问题,所以我加了另一个字段。详细信息可以参考 这里。
一般来说,切片一个查询集(QuerySet)会返回一个新的查询集,它并不会立即执行查询。更多信息可以参考 这里。
补充:我觉得这个请求的处理可能无法通过一个查询来完成。
data= [ ExampleModel.objects.filter(foreign_id=f)[0:2] for f in ForeignTable.objects.all()]
0
如果你知道怎么在SQL中实现这个功能,我建议你把这个限制作为一个额外的选项添加到Django的查询集中,就像在这个问题的被接受答案中那样。
你还可以查看Queryset的额外文档。
1
试着使用切片功能。
举个例子:
ExampleModel.objects.filter(ForeignTable__id=1).order_by('id')[:3]
这个代码会返回前面3个对象(限制为3个)。