Home > Net >  Django custom model manager for derived class - filtering on base class attribute
Django custom model manager for derived class - filtering on base class attribute

Time:12-29

I am using Django 3.2

I have the following models:

class AuthoriseableApprovedManager(models.Manager):
    def get_queryset(self):
        return super(AuthoriseablePendingManager, self).get_queryset().filter(computed_status=AUTHORISATION_STATUS_APPROVED)



class Authorisable(models.Model):
    # various fields ...
    approved_objects = AuthoriseableApprovedManager()

class ApprovedPublishedArticlesManager(models.Manager):
    def get_queryset(self):
        return self.approved_objects.filter(is_published=True)
    
    
    
class Article(Authorisable, 
              # Other base classes
              ):
    
    # various fields
    # ....

    objects = models.Manager() # The default manager.
    
    approved_published_articles = ApprovedPublishedArticlesManager()
    
    
    class Meta:
        ordering = ('-created_at', )

I have the following code in my views.py

class ArticleListView(ListView):
    model = Article

    def get_queryset(self):
        return self.model.approved_published_articles.all()  # <- Barfs here ...

I get the error message:

'ApprovedPublishedArticlesManager' object has no attribute 'approved_objects'

Which makes sense, since ApprovedPublishedArticlesManager does not derive from Authorisable.

How do I create a custom manager that allows me to filter based on base class properties - does my custom manager have to derive from models.Manager and the relevant base class (Authorisable in this case)?

CodePudding user response:

The problem is with the .get_queryset(…) method of your ApprovedPubhishedArtcilesManager. You can access the model with:

class ApprovedPublishedArticlesManager(models.Manager):
    def get_queryset(self):
        return self.model.approved_objects.filter(is_published=True)

although it might be better to inherit from AuthoriseableApprovedManager and make use of the base implementation of the .get_queryset(…) method. This is also more robust, since you do not have to take into account for what name that manager will be registered.

  • Related