Django queryset按相关字段的最新值排序

6

考虑以下 Django 中的模型:

class Item(models.Model):
  name = models.CharField(max_length = 100)

class Item_Price(models.Model):
  created_on = models.DateTimeField(default = timezone.now)
  item = models.ForeignKey('Item', related_name = 'prices')
  price = models.DecimalField(decimal_places = 2, max_digits = 15)

一个物品的价格可能会随着时间变化而不同,因此我想保留价格历史。

我的目标是使用Django ORM仅使用一个查询来获取商品列表及其最新价格,并按照价格升序排序结果。

如何才能最好地实现这一目标?


最好使用 django-simple-history,它会构建一个额外的历史记录表,使得查询“当前”状态更加容易。 - Willem Van Onsem
2个回答

1
你可以使用子查询来获取最新的Item_Price对象,并对其进行排序:
from django.db.models import <b>OuterRef, Subquery</b>

last_price = Item_Price.objects.filter(
    <b>item_id=OuterRef('pk')</b>
).order_by(<b>'-created_on'</b>).values('price')[:1]

Item.objects.annotate(
    <b>last_price=Subquery(last_price)</b>
).order_by(<b>'last_price'</b>)

对于每个Item,我们因此获得最新的Item_Price并在注释中使用它。
话虽如此,上述建模可能不是理想的,因为它将需要大量复杂的查询。django-simple-history [readthedocs.io]通过创建额外的模型并保存历史记录来以不同方式完成此操作。它还具有允许查询历史状态的管理器。这或许使处理历史数据更加简单。

0
您可以预取它们,以便像以下方式内联执行嵌套排序:
from django.db.models import Prefetch

prefetched_prices = Prefetch("prices", queryset=Item_Price.objects.order_by("price"))

for i in Item.objects.prefetch_related(prefetched_prices): i.name, i.prices.all()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接