2
\$\begingroup\$

We have Projects, which can each have many Entries. We want a report where we see the completion_date of the newest Entry associated with a given Project. However, we only want to consider Projects that have Entries after "2022-1-15".

Is this the best we can do or is there a more compact way to achieve this?

models.py

class Entry(models.Model):
    project = models.ForeignKey(related_name='entries')
    completion_date = models.DateTimeField()


class Project(models.Model):
    name = models.TextField(blank=True)

views.py

project_ids = Entry.objects \
    .filter(completion_date__gte=datetime.date("2022-1-15")) \
    .select_related('project') \
    .values_list('project', flat=True)


projects = Project.objects \
    .filter(id__in=set(project_ids), name=None) \
    .prefetch_related('entries') \
    .annotate(last_completion_date=Max('entries__completion_date'))

template.html

{% for project in projects %}
    {{project.name}}: {{project.last_completion_date}}
{% endfor %}
\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

I don't think you can go much more compact than that, but I suggest to extract queryset filters into QuerySet. You can extract parts of it into smaller pieces and chain them if necessary. That way you can reuse them and don't have long querysets in your views.

Something like this:

class ProjectQuerySet(models.QuerySet):
    def without_name(self):
        return self.filter(name=None)

    def completed_after(self, date):
        return self.filter(entries__completion_date__gte=datetime.date(date))

And then you have only very specific filters in your view, for example:

Project.objects.without_name().completed_after().distinct().order_by("pk")
\$\endgroup\$
0
\$\begingroup\$

Found this being more compact:

projects = Project.objects \
    .filter(name=None, entries__completion_date__gte=datetime.date("2022-1-15")) \
    .distinct() \
    .order_by("pk")
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.