Django ORM如何获取每个商品的最高价格及对应日期
解决方法
要获取每个商品的最高价格及对应日期,可以通过Django的Subquery和OuterRef实现,这是符合ORM规范的常用方式,适用于Django 2.0及以上版本:
步骤1:导入必要模块
from django.db.models import Subquery, OuterRef, Max
步骤2:编写查询代码
# 子查询1:获取每个商品对应的最高价格 max_price_subquery = Price.objects.filter( product=OuterRef('pk') ).values('product').annotate( max_price=Max('price') ).values('max_price') # 子查询2:根据最高价格匹配对应的日期 max_date_subquery = Price.objects.filter( product=OuterRef('pk'), price=OuterRef('max_price') ).values('date_seen')[:1] # 取第一条记录,避免同商品同价格多条记录的干扰 # 最终查询:为每个商品标注最高价格和对应日期 result = Product.objects.annotate( max_price=Subquery(max_price_subquery), max_price_date=Subquery(max_date_subquery) ).values( 'title', 'name', 'max_price', 'max_price_date' )
结果说明
- 执行后
result是一个QuerySet,每个元素是包含商品标题、名称、最高价格、对应日期的字典 - 若商品无价格记录,
max_price和max_price_date会返回None
简化方案(无重复最高价场景)
如果业务中每个商品的最高价格仅出现一次,也可以用Prefetch预加载关联记录:
from django.db.models import Max, Prefetch # 先获取每个商品的最高价格映射 product_max_prices = Price.objects.values('product').annotate(max_p=Max('price')) max_price_map = {item['product']: item['max_p'] for item in product_max_prices} # 自定义预加载查询,只获取每个商品的最高价记录 prefetch_max_price = Prefetch( 'price_set', queryset=Price.objects.filter( product__in=max_price_map.keys(), price=Subquery(Price.objects.filter(product=OuterRef('pk')).values('product').annotate(m=Max('price')).values('m')[:1]) ), to_attr='max_price_record' ) products = Product.objects.prefetch_related(prefetch_max_price).all() # 遍历提取数据 for product in products: if product.max_price_record: print(f"{product.title} 最高价: {product.max_price_record[0].price},日期: {product.max_price_record[0].date_seen}")
注意事项
- 你的模型代码中
Class需改为小写class,符合Python语法规范 - 若存在同一商品同一天多条相同最高价记录,
[:1]会取最早的那条,需全部记录可去掉切片
内容的提问来源于stack exchange,提问作者Gregg
相关产品推荐
相关产品推荐

