可以理解,外键可以具有related_name
,如下所示:
class Foo(Model):
...
class Bar(Model):
foo = ForeignKey(Foo, related_name='bars')
hidden = BooleanField()
效果是foo = Foo.objects.first(); foo.bars.all()
产生附着到该Bar
的任何Foo
。
但是,我想为所有.bars.all()
添加一个默认过滤器,以使标记为“隐藏”的Bar
永远不会成为结果查询集的一部分。
这很诱人:
class Foo(Model):
...
@property
def shown_bars(self):
return self.bars.filter(hidden=False)
,仅使用foo.shown_bars
而不是foo.bars
,但我的目标是也使这样的related_name
嵌套可预取,即
class Baz(Model):
foo = ForeignKey(Foo)
# The bars in this queryset *also* automatically excludes bars that are hidden.
# Using `shown_bars` here undoes the prefetch.
Baz.objects.prefetch_related('foo__bars')
因此nested_bars
不能在此类表达式中直接使用。
在Django 1.11或2.x中有实现此目的的方法吗?
答案 0 :(得分:0)
对prefetch_related
操作中检索到的查询集施加控制的首选方法是使用Prefetch
中引入的Django 1.7对象。
您定义所需的查询集:
filtered_bars = Bar.objects.filter(wanted=True)
或者,如果您在filtered
上定义了custom manager Bar
:
filtered_bars = Bar.filtered.all()
然后您在select_related
调用中使用查询集:
Baz.objects.prefetch_related(Prefetch(
'bars',
queryset=filtered_bars))
人们可能想到的另一种选择是操纵相关对象(这里为Bar
)的基础管理器,这将自动影响默认的预取操作。但是,Django docs明确警告不要这样做,因为这样做会阻止Django访问所有对象,这是它必须能够执行的操作。