如何覆盖我考虑以下内容的多对多字段的模型管理器:
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?
最佳答案
首先,您不应该重写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_lated_fields = True
),因为您将屏蔽数据库中实际存储的内容,而不是简单地检测过时的数据并创建警报或其他方式来清理它。 use_for_lated_fields
旨在创建增强普通管理器正常功能的管理器,而不是用于过滤。
我遇到过和你类似的情况,我是这样处理的:
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
特定对象添加到自定义管理器中,并且不从对从 Object
获取 Term
查询集进行操作的方法中调用它们呢?
关于python - Django,覆盖多对多字段ModelManager,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13610633/