使用ManyToManyField的Django自定义管理器

Bry*_*ard 11 django django-models

我有一个带有ManyToManyField的模型,其中有一个直通模型,其中有一个我希望过滤的布尔字段.

from simulations.models import *
class DispatcherManager(models.Manager):
    use_for_related_fields = True

    def completed(self):
        original = super(DispatcherManager,self).get_query_set()
        return original.filter(dispatchedsimulation__status=True)
    def queued(self):
        original = super(DispatcherManager,self).get_query_set()
        return original.filter(dispatchedsimulation__status=False)

class Dispatcher(models.Model):
    name = models.CharField(max_length=64)
    simulations = models.ManyToManyField('simulations.Simulation',
            through='DispatchedSimulation')
    objects = DispatcherManager()

class DispatchedSimulation(models.Model):

    dispatcher = models.ForeignKey('Dispatcher')
    simulation = models.ForeignKey('simulations.Simulation')
    status = models.BooleanField()
Run Code Online (Sandbox Code Playgroud)

我认为use_for_related_fields变量允许我过滤m2m结果,就像调度员那样:d.simulations.completed()或者d.simulations.queued()这些似乎不像我预期的那样工作.我误解了use_for_related_fields作品是怎么回事,还是我做错了什么?

Ofr*_*viv 3

来自使用管理器进行相关对象访问的文档:

您可以通过在管理器类上设置 use_for_lated_fields 属性来强制 Django 使用与模型的默认管理器相同的类。

这意味着,在您的情况下,您可以强制d.simulation使用普通的SimulationManager(而不是DispatcherManager - DispatcherManager 将用于链接的相反方向。例如,Simulation.objects.get(id=1).dispatcher_set.completed)。

我认为实现你想要的最简单的方法是在 DispatcherManager 中定义 aget_completed_simulations和 aget_queued_simulations方法。所以用法是d.get_completed_simulations().