Search code examples
pythondjangodjango-orm

django - Creating custom queryset for RelatedManager


I tried about 25 Stackoverflow links and nobody seems to have a working solution for this problem.

I created a custom queryset like this:

class ProjectQuerySet(models.QuerySet):
   def get_active(self):
       from apps.projectmanagement.models import Project
       return self.filter(active=True)

class ProjectManager(models.Manager):
  def get_queryset(self):
      return ProjectQuerySet(self.model, using=self._db)

This works great if I start at the model like

Project.objects.get_active()

But if I want to use it in a relation, no luck so far:

employee.projects.get_active()

I always get this error:

AttributeError: 'ManyRelatedManager' object has no attribute 'get_active'

What I've tried so far:

  1. I read that use_for_related_fields = True in the manager class is deprecated. Does not work anyway on django v2.1

  2. Adding this in my model, as half the internet states:

    class Project(models.Model): ... objects = ProjectManager()

    class Meta:
        base_manager_name = 'objects'
    
  3. Trying to avoid the RelatedManager and to work with a queryset:

    employee.projects.all().get_active()

Any ideas what I've been doing wrong? And how would I solve this? Can't be too hard, right?


Solution

  • As the docs state, "Base managers aren’t used when querying on related models". The example they give is for going in the other direction, ie project.employee.

    There is no way to do this using managers themselves. The best bet is to define a method on your model:

    class Employee(models.Model):
        ...
        def get_active_projects(self):
            return self.projects.filter(active=True)
            # or
            return Project.objects.filter(employee=self).get_active()