Back
Jul 1, 2010

Overriding QuerySet in Django

As you know, model managers can be overriden in Django. It's convenient to add custom filtration method there:

Article.objects.published()
Article.objects.old()

But these custom methods cannot be chained:

Article.objects.published().old()

Overriding manager doesn't allow it, because after first manager method is invoked (published in this case), we receive queryset as a result, which knows nothing about custom manager methods. So we have to add custom methods to queryset. This can look like this:

class ArticleQuerySet(models.query.QuerySet):

    def published(self):
        return self.filter("...")

    def old(self):
        return self.filter("...")

Now we need to make manager user this class. In order to do this, let's override manager's get_query_set method:

class ArticleManager(models.Manager):

    def get_query_set(self):
        return ArticleQuerySet(self.model, using=self._db)


class Article(models.Model):
    # ...

    objects = ArticleManager()

This allows to make queties like:

Article.objects.all().published().old()

Here we invoke all to get queryset instance, because this time manager doesn't have custom methods - published and old. To avoid this, we can make manager look for undefined methods in queryset:

class ArticleManager(models.Manager):

    def get_query_set(self):
        return ArticleQuerySet(self.model, using=self._db)

    def getattr(self, key):
        return getattr(self.get_query_set(), key)

Note that getattr is only invoked when attribute is not found by usual means.

Manager can be further improved to be more generic:

class QuerySetManager(models.Manager):

    def init(self, queryset_class, args, **kwargs):
        self.queryset_class = queryset_class
        super(QuerySetManager, self).init(args, **kwargs)

    def get_query_set(self):
        return self.queryset_class(self.model, using=self._db)

    def getattr(self, key):
        return getattr(self.get_query_set(), key)


# Now you can simply write:
# objects = QuerySetManager(ArticleQuerySet)

 

Update

After article was published, I found out that this idea is not all that new and unique :)

It's funny that only after I implemented my own solution, I've managed to make correct search query.

Subscribe for the news and updates

More thoughts
Dec 22, 2024Technology
Python and the Point Rush in DeFi

This article demonstrates how to use Python to automate yield calculations in decentralized finance (DeFi), focusing on the Renzo and Pendle platforms. It guides readers through estimating potential rewards based on factors like token prices, liquidity, and reward distribution rules, emphasizing the importance of regular data updates and informed decision-making in DeFi investments.

Sep 8, 2023Technology
Smooth React virtual scroll with fixed rows/columns

One of our ongoing projects, Neptyne, introduces an Excel-like grid written in React. We used a library to apply virtual scroll to it, but we stumbled upon a problem with fixed rows and columns inside the grid. Here I would like to describe this problem, how it occurs, and how we handled it.

Dec 8, 2022Technology
How to create a route finder on an SVG map

In one of our recent projects, we had an interesting case: the whole application was built around an interactive map for a fairly large shopping mall, and the main goal of the system was to plot the closest route to a user-selected destination.

Sep 1, 2021TechnologyBusiness
Top 10 Web Development Frameworks in 2021 - 2022

We have reviewed the top web frameworks for server and client-side development and compared their pros and cons. Find out which one can be a great fit for your next project.

Oct 3, 2016Technology
How to include JQuery plugins in Angular 2 running via webpack

Learn more about how to include jquery plugins in angular 2 running via webpack. Our tutorial is perfect for Angular beginners.

Feb 18, 2010Technology
User profiles with inheritance in Django

Usually users' profiles are stored in single model. When there are multiple user types, separation is made by some field like user_type.Situation is a little more complicated when different data is needed for each user type.In this article I'll describe how I solve this task.