[英]Django: Filter on related model's field not being equal to a specific value
[英]Django filter related field using related model's custom manager
在通过相关字段进行过滤时,如何从自定义管理器查询集应用注释和过滤器? 这里有一些代码来证明我的意思。
经理和模特
from django.db.models import Value, BooleanField
class OtherModelManager(Manager):
def get_queryset(self):
return super(OtherModelManager, self).get_queryset().annotate(
some_flag=Value(True, output_field=BooleanField())
).filter(
disabled=False
)
class MyModel(Model):
other_model = ForeignKey(OtherModel)
class OtherModel(Model):
disabled = BooleanField()
objects = OtherModelManager()
尝试使用管理器过滤相关字段
# This should only give me MyModel objects with related
# OtherModel objects that have the some_flag annotation
# set to True and disabled=False
my_model = MyModel.objects.filter(some_flag=True)
如果您尝试上面的代码,您将收到以下错误:
TypeError: Related Field got invalid lookup: some_flag
为了进一步澄清,基本上相同的问题被报告为一个错误,没有回应如何实际实现这个: https : //code.djangoproject.com/ticket/26393 。
我知道这可以通过直接在MyModel
过滤器中直接使用管理器中的过滤器和注释来实现,但重点是保持此DRY并确保在访问此模型的任何地方重复此行为(除非明确指示不)。
如何运行嵌套查询(或两个查询,以防您的后端是MySQL;性能)。
第一个获取相关OtherModel
对象的pk。
第二个是在获取的pks上过滤Model
对象。
other_model_pks = OtherModel.objects.filter(some_flag=...).values_list('pk', flat=True)
my_model = MyModel.objects.filter(other_model__in=other_model_pks)
# use (...__in=list(other_model_pks)) for MySQL to avoid a nested query.
我不认为你想要什么是可能的。
1)我认为你错过了解注释的作用。
为QuerySet中的每个项生成聚合
生成汇总值的第二种方法是为QuerySet中的每个对象生成独立摘要。 例如,如果您要检索书籍列表,您可能想知道有多少作者为每本书做出了贡献。 每本书都与作者有多对多的关系; 我们想要总结QuerySet中每本书的这种关系。
可以使用annotate()子句生成每对象摘要。 指定annotate()子句时, QuerySet中的每个对象都将使用指定的值进行批注。
这些注释的语法与用于aggregate()子句的语法相同。 annotate()的每个参数都描述了要计算的聚合。
所以当你说:
MyModel.objects.annotate(other_model__some_flag=Value(True, output_field=BooleanField()))
你是不是注释some_flag
过other_model
。
即你不会: mymodel.other_model.some_flag
您正在other_model__some_flag
上注释mymodel
。
即你将拥有: mymodel.other_model__some_flag
2)我不确定SQL
对你有多熟悉,但是为了保留MyModel.objects.filter(other_model__some_flag=True)
,即在进行JOINS
时保留注释, ORM
必须在subquery
进行JOIN
, 就像是:
INNER JOIN
(
SELECT other_model.id, /* more fields,*/ 1 as some_flag
FROM other_model
) as sub on mymodel.other_model_id = sub.id
这将是超级慢,我并不惊讶他们没有这样做。
不要注释您的字段,而是将其添加为模型中的常规字段。
简化的答案是模型对字段集合具有权威性,而管理者对模型集合具有权威性。 在你努力使它干涸的时候,你做了WET,因为你改变了经理的字段集。
为了解决这个问题,你必须教会模型有关查找的信息,并且需要使用Lookup API来完成 。
现在我假设您实际上没有使用固定值进行注释,因此如果该注释实际上可以简化为字段,那么您可能只是将其完成,因为最终它需要映射到数据库表示。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.