简体   繁体   English

Django查询集按相关字段中的最新值排序

[英]Django queryset order by latest value in related field

Consider the following Models in Django:考虑 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)

The price of an item can vary throughout time so I want to keep a price history.商品的价格会随时间变化,因此我想保留价格历史记录。

My goal is to have a single query using the Django ORM to get a list of Items with their latest prices and sort the results by this price in ascending order.我的目标是使用 Django ORM 进行单个查询以获取具有最新价格的项目列表,并按此价格按升序对结果进行排序。

What would be the best way to achieve this?实现这一目标的最佳方法是什么?

You can use a Subquery to obtain the latest Item_Price object and sort on these:您可以使用Subquery来获取最新的Item_Price对象并对这些对象进行排序:

from django.db.models import OuterRef, Subquery

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

Item.objects.annotate(
    last_price=Subquery(last_price)
).order_by('last_price')

For each Item , we thus obtain the latest Item_Price and use this in the annotation.对于每个Item ,我们因此获得最新的Item_Price并在注释中使用它。

That being said, the above modelling is perhaps not ideal, since it will require a lot of complex queries.话虽如此,上述建模可能并不理想,因为它需要大量复杂的查询。 django-simple-history [readthedocs.io] does this differently by creating an extra model and save historical records. django-simple-history [readthedocs.io]通过创建一个额外的模型并保存历史记录来做到这一点。 It also has a manager that allows one to query for historical states.它还有一个管理器,允许查询历史状态。 This perhaps makes working with historical dat simpeler.这可能使使用历史数据更简单。

You could prefetch them in order to do the nested ordering inline like the following:您可以预取它们以进行内联嵌套排序,如下所示:

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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM