Debugging dynamic querysets in Django

Class-based views in Django are super handy. Among other things, you can create a view listing all instances of a model with about two lines of code.

One of the features of this ListView is the ability to customize the queryset used to populate the view. Suppose you wanted a view to list all the Foos in your database - no problem:

class FooView(ListView):
    model = Foo

Django also lets you customize the queryset, in case you don't want all Foos:

class FooView(ListView):
    """List all the Foos that aren't bar"""
    model = Foo
    queryset = Foo.objects.filter(bar=False)

I had to debug a problem with this. Django lets you specify a dynamic queryset by overriding the method get_queryset(). I was trying to do so by just overriding queryset. If you do that, Django will only evaluate it once, on startup. In my case, it was a time-based filter:

class FooView(ListView):
    """List all the Foos in the past"""
    model = Foo
    queryset = Foo.objects.filter(timestamp__lt=timezone.now())  # <- doesn't do what you think!

So my results would look right immediately after startup, but get more and more out of whack the longer the app ran. This ended up fixing my problem:

class FooView(ListView):
    model = Foo

    def get_queryset(self):
        return Foo.objects.filter(timestamp__lt=timezone.now())

Happy coding.