tags:

views:

143

answers:

3

django's manager docs has a paragraph overwritten with DO NOT FILTER AWAY ANY RESULTS IN THIS TYPE OF MANAGER SUBCLASS, but in the following text only mentions get_query_set()

Is it save to filter in all(), get(), filter(), exclude()?

The reason why I want to do that: I want for the automatic Manager as it gives my the power to control, what rows are send to a template-tag as described in b-list: Write better template tags

Would this code be OK?

class ArticleMananger(models.Manager):
    def get_query_set(self):
        return super(ArticleMananger, self).get_query_set()
    def all(self): 
        return super(ArticleMananger, self).filter(published=True)   
    def filter(self,  **kwargs):
        return super(ArticleMananger, self).filter(published=True).filter(**kwargs) 
    ....


Edit: If someone votes down, it would be nice or just fair to explain why. What is wrong about this question?

+3  A: 

I think, this is a warning only to not override the method get_query_set() in your models.Manager subclass without further consideration of the use of this method by Django itself if this manager gets the default (objects) manager of your model. You might experience hard to debug behavior otherwise.

Try to add print statements to your overridden methods to see when and how often they are used by other apps (i.e. the admin app).

aldi
+1  A: 

I did some test and will answer my own question:

Do not filter in all(),... too!

I just tried it out. It breaks parts of the admin interface. From a technical point of view it could be possible to overwrite / extend template/admin/apps/* to use another manager (ie via own tags), but I come to the conclusion, that it wont worth the work. Instead I will rewrite my tags to something like this:

def render(self, context):
    if hasattr(self.model, 'publicmgr'):
        context[self.varname] = self.model.publicmgr.all().order_by(self.by)[:self.num]
    else:
        context[self.varname] =   self.model._default_manager.all().order_by(self.by)[:self.num]
    return  ''
vikingosegundo
You could reduce duplication here by just storing a reference to your preferred manager in a local variable inside the if/else, then doing the ordering and slicing only once.
Carl Meyer
That is true. And will look more elegantly
vikingosegundo
+1  A: 

The basic idea is that if you change the way the default manager for your model retrieves objects in common methods like all() or filter(), you will eventually run into a situation where you want to retrieve some particular object but can't. Often this will be difficult to diagnose because it'll turn up as objects mysteriously not appearing, or DoesNotExist exceptions where you didn't expect them.

So long as you keep a default manager around that can retrieve everything normally, it's fine to do custom stuff in other managers on the same class, though.

James Bennett