Django QuerySet:按特定字段限制结果分组

4 投票
3 回答
767 浏览
提问于 2025-04-18 15:05

我搜索了一下,没找到办法来实现以下需求:

假设我们有一个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_iduser_idExampleModels。但我只想从一组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_bydistinct 一起用可能会出现问题,所以我加了另一个字段。详细信息可以参考 这里

一般来说,切片一个查询集(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个)。

撰写回答