我有以下内容:
class Product(models.Model):
name = models.CharField(max_length=255)
class Action(models.Model):
product = models.ForeignKey(Product)
created_at = models.DateTimeField(auto_now_add=True)
我想检索created_at DESC使用不同产品订购的10个最新动作。
以下是接近结果,但仍然错过了顺序:
Action.objects.all().order_by('product_id').distinct('product_id')[:10]
答案 0 :(得分:15)
您的解决方案似乎正在尝试做太多。它还将导致2个单独的SQL查询。这样可以正常工作,只需一个查询:
action_ids = Action.objects.order_by('product_id', '-created_at')\
.distinct('product_id').values_list('id', flat=True)
result = Action.objects.filter(id__in=action_ids)\
.order_by('-created_at')[:10]
答案 1 :(得分:4)
编辑:这个解决方案有效,但Ross Lote更干净
这是我最终使用Django Aggregation:
的方式from django.db.models import Max
actions_id = Action.objects.all().values('product_id') \
.annotate(action_id=Max('id')) \
.order_by('-action_id')[:10] \
.values_list('action_id', flat=True)
result = Action.objects.filter(id__in=actions_id).order_by('-created_at')
通过设置values('product_id')
,我们在 product_id 上按执行组。
使用annotate()
,我们只能对values()
或annotate()
中使用的字段使用 order_by 。由于对于每个操作, created_at 字段自动设置为现在, created_at 上的排序与 id 上的排序相同,使用{{1}是正确的方法。
Finnaly,我们只需切片查询annotate(action_id=Max('id')).order_by('-action_id')
希望这有帮助。