Search code examples
djangodjango-modelsdjango-managers

How do I use a ModelManager on a Django ManyToMany through field?


Let's say I have the following models:

class Poll(model):
     title = models.CharField()

class Option(model):
     title = models.CharField()
     polls = models.ManyToManyField(
         Poll, 
         through='PollOption', 
         null=True, 
         blank=True, 
         related_name='options'
     )

class PollOptionManager(models.Manager):
    use_for_related_fields = True
    def get_queryset(self):
        return super(PollOptionManager, self).get_queryset().filter(
            is_active=True
        )

class PollOption(model):
     poll = ForeignKey(Poll)
     option = ForeignKey(Option)
     is_active = BooleanField(default=True)
     objects = PollOptionManager()

When I try to query Poll.options.all() I'm still getting Option instances for which PollOption.is_active is False. How can I get my model manager to appropriately filter my ManyToMany relationship based on a flag on the through field?


Solution

  • The problem is that the through model's (related) manager is never actually used in your scenario. In order to utilize the custom manager, you have to explicitly use it, e.g.:

    class Poll(models.Model):
    
        @property
        def active_options(self):
            return Option.objects.filter(id__in=self.polloption_set.values_list('option'))
    

    Here, polloption_set filters out inactive options as intended. This, however, makes the manager kind of pointless because you can just as well put the extra filter in the custom property.