【问题标题】:Django annotate min and max of filtered foreign keyDjango注释过滤外键的最小值和最大值
【发布时间】:2019-03-19 22:23:24
【问题描述】:
class Price(models.model):
    value = models.DecimalField(...)
    stock = models.ForeignKey("Stock", related_name='prices')

class Stock(models.model):
    current_evlauation = models.ForeignKey('Price')
    last_hour_evlauation = models.ForeignKey('Price')

在以mysql为数据库的Django 1.11.13中,我想优化以下几行代码:

last_hour = datetime.datetime.now() - datetime.timedelta(hours=2)
stock_list = Stock.objects.all()

for stock in stock_list:
    stock.last_hour_evaluation = stock.prices.filter(date__gte=last_hour).earliest('date')
    stock.current_evaluation = stock.prices.latest('date')
    stock.save()

stock_deltas = list(Stock.objects.annotate(delta=F('current_evaluation__value)-F('last_hour_evaluation__value')).values_list('delta', flat=True))

类似:

stock_deltas = list(Stock.objects\
                         .annotate(current_eval=..., last_eval=...)\
                         .annotate(delta=F('current_eval') -F('last_hour_eval'))\
                         .values_list('delta', flat=True))

(stock_deltas = 最近一小时的股票价格变化列表)

有可能做这样的事情吗? 否则,如何使用最少的查询来编写第一段代码?

【问题讨论】:

    标签: python mysql django optimization annotations


    【解决方案1】:

    您可以将MaxMinQ objects 结合起来进行复杂过滤

    Stock.objects.all().annotate(
        current_eval=Min('prices__date', filter=Q(prices__date__gte=last_hour)),
        last_eval=Max('prices__date')).annotate(
        delta=F('current_val') - F('last_eval'))
    

    【讨论】:

    • 这不是只标注价格的日期吗? (Max 有过滤器作为 kwarg 吗?我看过 docs.djangoproject.com/en/1.8/_modules/django/db/models/… 但我没找到)
    • 我不确定旧版本,但在 2.0 中所有 aggregate functions 接受过滤器。您能否使用预期结果更新您的问题,因为这将优化您在 OP 中提供的代码。
    • 是的,不幸的是过滤器仅在 django 中可用>=2.0。但是 "current_eval=Min('prices__date', ...)" 不会将 current_eval 设置为日期?
    猜你喜欢
    • 1970-01-01
    • 2017-10-13
    • 2018-10-09
    • 1970-01-01
    • 2019-08-17
    • 1970-01-01
    • 1970-01-01
    • 2015-10-17
    • 1970-01-01
    相关资源
    最近更新 更多