Django’s Annotate Filter

I’ve been doing a bit of work lately trying to gather some analytics on users. I’m going to use the example of a sports application where people can create and join multiple teams. The other day I was writing a queryset that would fetch the users who have joined their first team in the last week. It’s trivial to write this queryset on multiple lines. Depending on how you set up your models, it may look like this:

users = []
 
for user in User.objects.all().iterator():
    if min(user.team_set.all().values_list('created_at')) in date_range:
        users.append(user)

It might take you an extra read over to understand what is going on here. I’m iterating through each user in the db. For each user I get the creation dates of each team they are a part of and check that the minimum of these dates is in the date range we want. Phew.

A nicer way to do this is using Django’s annotate filter. You can use it to summarize information about each object. Here is how annotate would be used with this example:

users = User.objects.annotate(first_team_date=Min("team__created_at"))
users = users.filter(first_team_date__range=date_range)

I find this much easier to read at first glance, making this code much more maintainable.

Category(s): Uncategorized

Leave a Reply

Your email address will not be published. Required fields are marked *

 

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>