如何覆盖我考虑过以下内容的多对多字段的模型管理器:
class TermsManager(models.Manager):
def all(self):
return super(TermsManager, self).all().filter(condition_here)
class Term(models.Model):
objects = TermsManager()
name = models.CharField(max_length=255)
class Object(models.Model):
title = models.CharField(max_length=255)
terms = models.ManyToManyField(Term, blank=True)
class Channel(Object):
class Meta:
proxy = True
我还有一个继承自TermManager的类,名为ChannelTermManager。 如何覆盖Channel模型的“terms”字段 mychannel.terms调用ChannelTermManager而不是TermManager?
答案 0 :(得分:2)
首先,你不应该覆盖all()
。如果要更改默认查询集,请覆盖get_query_set
,如下所示:
class TermsManager(models.Manager):
def get_query_set(self):
return super(TermsManager, self).get_query_set().filter(condition_here)
这是因为当链接其他查询集函数时,all()
经常被省略,并且您希望查询集的行为相同,无论是否显式调用all()
。
但即便如此,你所做的仍然是有问题的。如documentation for managers中所述,过滤默认的相关查询集将影响幕后的各种自动操作(例如,在转储数据以创建备份/夹具等时)。 你几乎肯定不想要这个。并且您真的不希望您的相关对象管理器这样做(通过设置use_for_related_fields = True
),因为您将屏蔽实际存储在数据库中的内容,而不是简单地检测过时数据并创建警报或其他清理它。 use_for_related_fields
用于创建管理器,以增强vanilla管理器的正常功能,而不是过滤。
然而,我遇到了类似的情况,我这样处理了它:
class FilteredTermsManager(models.Manager):
def get_query_set(self):
return super(TermsManager, self).get_query_set().filter(condition_here)
class Term(models.Model):
allTerms = models.Manger() # Establish this as the default/automatic manager
objects = FilteredTermsManager()
name = models.CharField(max_length=255)
这样,我可以通过我的过滤查询集对模型进行所有初始查询,它看起来像“常规Django”,但所有关系和幕后查询都可以在未过滤的数据库上运行。我总是可以通过手动执行Term.allTerms.all()
来访问真正的完整对象。
至于为不同的相关对象使用不同的管理器,那里没有什么可以真正做到的。但是,为什么不将Channel
个特定对象添加到自定义管理器中,而不是从Term
来自Object
查询集的操作方法中调用它们?