自定义模型管理器被prefetch_related破坏了

时间:2020-08-24 19:30:13

标签: python django

我有一个模型和一个相应的模型管理器:

class MyModelManager(models.Manager):
    def get(self, **kwargs):
        return super().select_related('group').get(**kwargs)

class MyModel(models.Model):
    name = models.CharField(...)
    group = models.ForeignKey('Group', ...)
    tags = models.ManyToManyField('Tag', ...)
    # ... others ...

    objects = MyModelManager()

模型管理器在select_related()例程中执行get(),以便始终连接给定的外键字段(我可能会经常引用它)。当我调用get()例程时,事情按预期运行:

obj = models.MyModel.objects.get(pk=1)
print(obj.group)  # Doesn't hit the database a second time

但是,如果我拨打类似prefetch_related()之类的电话,则我的自定义管理器会被丢弃:

obj = models.MyModel.objects.prefetch_related('tags').get(pk=1)
print(obj.group)  # Hits the database a second time to get the group

当我打印类型时,原因就很清楚了

x = models.MyModel.objects
print(type(x))  # Yields <class 'base.models.TestCaseManager'>
y = models.MyModel.objects.prefetch_related('tags')
print(type(y))  # Yields <class 'django.db.models.QuerySet'>

我的问题

我可以通过链式调用返回我的自定义管理器实例,而不是默认实例吗?

1 个答案:

答案 0 :(得分:1)

模型管理器的API定义显式返回QuerySet对象,而不返回管理器对象。假设管理器已正确实现,返回的QuerySet仍具有管理器的所有自定义设置。 prefetch_related没什么特别的,filterallnoneannotate等也是如此。基本上,管理器对象是{的生成器{1}}个对象以及许多QuerySet方法也是QuerySet对象的生成器。调用生成QuerySet的方法后,您不应期望能够调用诸如get_or_create之类的特定于管理器的方法。

相关问题