views:

51

answers:

2

I have added a 'cancelled' field to my model, is there a way to modify the model default query to something like cancelled=False ? without having to modify all my filter/exclude queries ?

+4  A: 

You can do this with a custom model manager and override the get_query_set function to always filter canceled=False.

class CustomManager(models.Manager):
    def get_query_set(self):
        return super(CustomManager, self).get_query_set().filter(canceled=False)

class MyModel(models.Model):
    # Blah blah
    objects = CustomManager()

Then when calling MyModel.objects.all() it will always exclude canceled objects. Here is a blog post I found helpful on the subject. http://www.b-list.org/weblog/2006/aug/18/django-tips-using-properties-models-and-managers/

EDIT: Perhaps a better approach with a custom manager would be to attach it to another property, other than objects, such as:

class MyModel(models.Model):
    # Blah blah
    active = CustomManager()

And in your views your queries would look like MyModel.active.all().

Mark Lavin
you have to be VERY VERY careful with overriding default manager just like that. In this particular case, once item is cancelled, you won't ever find it with filter()/get().
Dmitry Shevchenko
Agreed. Would I typically supplement this approach with overriding get() to not use this filter if the pk is given. You probably would also want to change the admin queryset to return all including canceled. But if you rarely want canceled items in your queries this can be a reasonable approach.
Mark Lavin
+2  A: 

You could write custom query manager, but I don't believe this is the right way to go. This would make an implicit, hidden condition for a filter, which would make code unreadable. Remember Zen of Python: Explicit is better than implicit. Detect places, where you need to add cancelled=False and just add this, that's the way you should do this.

gruszczy
I strongly disagree. What, then, would be the point of having custom managers? What is so implicit about `not_cancelled = CustomManager()` and then using MyModel.not_cancelled.all()?
jonwd7