【问题标题】:Django .values() after F() expression filterF() 表达式过滤器后的 Django .values()
【发布时间】:2018-02-12 12:12:48
【问题描述】:

在您使用带有 F() 表达式的过滤器后,似乎 Django 无法对值进行分组。例如:

(模型.py)

class Athlete(models.Model):
    name = models.CharField(max_length=30)
    nationality = models.CharField(max_length=30)

class TrainingSession(models.Model):
    training_date = models.DateTimeField()
    location = models.CharField(max_length=30)
    athlete = models.ForeignKey(Athlete)

class Run(models.Model):
    run_time = models.IntegerField()
    training = models.ForeignKey(TrainingSession)

(views.py) 我想要他们跑得最好的每个位置的跑步者数量。

r = Run.objects.all()

# Annotate the best time from the training session and filter
r = r.annotate(best_run_time = Min('trainingsession__run__run_time'))
r = r.filter(run_time = F('best_run_time'))

# Group by location
r = r.values('location')
r = r.annotate( athlete_count = Count('trainingsession_athlete', distinct=True))

当我不使用F() 表达式时,.values('location') 将对每个位置的结果进行分组。但是,当我使用它时,每个位置都会被多次指定,且 player_count 为 1。

【问题讨论】:

  • 你如何获得“跑得最好的每个位置的跑者数量”? (只有一个有 best_runtime 的位置)
  • 是的,但是对于某个位置,多个跑步者可能会跑得最好。
  • 如果一名运动员在两个地点的时间相同,你会怎么做?它应该在这两个地方都算他吗?我想是的,只是澄清一下。

标签: python django django-queryset


【解决方案1】:

首先,r.annotate(best_run_time = Min('trainingsession__run__run_time')) 将为每个 Run 对象注释不同的时间,这不是您所期望的。您希望将所有内容都包含在查询集中,但对每个对象分别进行注释,因此如果 Run 对象的 run_time 为 10 个单位,那么 10 也会被注释。你真正需要的是aggregate(),你可以这样使用:

><> best = Run.objects.all().aggregate(Min('run_time'))
><> best
>>> {'run_time__min': 10}

您的查询可以这样工作:

Run.objects.filter(run_time=best['run_time__min']).values('location')  

在使用F、注释和过滤时,Django 查询集存在一些问题,但不知道您使用的是哪个 Django 版本,很难为您指明正确的方向。

【讨论】:

    猜你喜欢
    • 2015-09-01
    • 2014-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    • 2019-10-02
    相关资源
    最近更新 更多