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 Foo
s 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.