简体   繁体   中英

Django .values() after F() expression filter

It seems that Django can not group values after you use a filter with an F() expression. For example:

(models.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) I want the number of runners for every location where they had their best run.

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

When I don't use the F() expression, the .values('location') will group the result per location. However, when I use it, every location is given multiple time with an athlete_count of 1.

First of all, r.annotate(best_run_time = Min('trainingsession__run__run_time')) will annotate a different time to every Run object which is not what you expect. You want to include everything in the queryset, but annotating does it for each object separately, so if a Run object has a run_time of 10 units, then 10 is also annotated. What you really need is aggregate() that you can use like this:

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

Your query could work like this:

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

There are some problems with Django querysets when using F , annotations and filtering, but without knowing which Django version you are using, it's kinda hard to point you in the correct direction.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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