Django 1.9: Create complex custom filter method for QuerySet

Viewed 989

The goal is to create a custom_filter method that can be chained to standard Django filter methods. The custom_filter method likely requires some raw SQL code. In the best case, the QuerySet would still be evaluated lazy.

In the end, such a command would be great:

apple_query_set = Apple.objects.filter(<any standard filtering>).custom_filter()

This is the model:

class Apple(models.model):
    a = models.IntegerField()
    b = models.IntegerField()
    date = models.DateField()

The goal of the custom_filter is to group the Apple instances by (a,b), and for each group return only the newest instance according to date.

The raw SQL code for such a filter is as follows:

custom_filter_raw_sql = """
SELECT t1.id
FROM app_apple AS t1
INNER JOIN (SELECT a, b, max(date) AS max_date
            FROM app_apple
            GROUP BY a, b) AS t2
ON t1.a = t2.a AND t1.b = t2.b AND t1.date = t2.max_date;
"""

So far, in order to add the custom_filter functionality, I've tried (unsuccessfully) adding objects = AppleQuerySet.as_manager() to the Apple class, with:

 class AppleQuerySet(models.QuerySet):
    def custom_filter(self):
        subquery = """
        SELECT t1.id
        FROM app_apple AS t1
        INNER JOIN (SELECT a, b, max(date) AS max_date
                    FROM app_apple
                    GROUP BY a, b) AS t2
        """
        condition = "t1.a = t2.a AND t1.b = t2.b AND t1.date = t2.max_date"
        return self.extra(tables=[subquery], where=[condition])

However, I'm not sure this approach stands a chance to work, as the custom query should not only work on all Apple instances (Apple.objects.), but it should be possible to chain it to a filtered queryset (Apple.objects.filter())

What is the best approach to create this custom chainable, (lazy) custom_filter functionality? Where am I going wrong? Thanks a lot!

2 Answers
Related