I have two models, Project and Session. One project has many sessions, one user has many projects:
class Project(models.Model):
class Meta:
ordering = [models.functions.Lower("name")]
name = models.CharField(max_length=255)
user = models.ForeignKey(User, on_delete=models.CASCADE)
class Session(models.Model):
start = models.DateTimeField()
end = models.DateTimeField()
timezone = TimeZoneField()
breaks = models.IntegerField(default=0, validators=[MinValueValidator(0)])
project = models.ForeignKey(Project, on_delete=models.CASCADE)
def duration(self):
# returns minutes in (end - start)
I want a way to get all projects for a given user, sorted by the sum of duration in all its sessions. As session.duration()
is not a database field, but rather is calculated from database fields, I cannot get this information in a single database query.
My current solution is:
sessions = Session.objects.filter(project__user=self)
groups = [[a, sum([s.duration() for s in b])] for a, b in groupby(
sessions, key=lambda s: s.project
)]
groups = sorted(groups, key=lambda g: g[1], reverse=True)
return [g[0] for g in groups]
This gets all relevant sessions in a single query, but then I group them by project and this takes too long - about a second when there are about a 100 projects. Is there a way to accomplish this that takes less time? And ideally doesn't require a database call for every project?
I am using Django 2.0.