【问题标题】:Queryset filtering by multiple FK attributes通过多个 FK 属性进行查询集过滤
【发布时间】:2020-10-07 12:25:14
【问题描述】:

我的情况:

我有 django 模型 HOST 和模型 PACKAGE(带有名称和版本),在 host 模型上有 FK。现在我需要过滤所有具有 packageshosts 具有某些 name 和某些 version.. 因此类似于@ 987654321@ 这一切都很好,也很简单,但是我需要对几个包重复这个操作,这样我才能得到一个主机,它在一个版本中包含每个希望的包..

我尝试了两种方法,但都失败了,首先是在 for 循环中应用上面的 filter,它很丑但很有效,我很高兴我发现这不是稳定的解决方案,而且有些我接下来应用 SOMETIMES 的查询失败.. 有时是的!正如我对自己说的那样,我不会更深入 Django ORM 魔法的那个洞,我尝试用 Q 构建查询。我最终得到了以下代码

pckgs_query = reduce(
    operator.and_,
    (
        Q(packages__name=name, packages__version__in=versions)
        for name, versions in pckgs_dict.items()
    )
 )
hosts = Host.objects.filter(pckgs_query)

但不幸的是,这不能正常工作,因为我检查了它生成的 SQL 查询,我确定它正在寻找具有所有这些参数的单个 PACKAGE 对象,这些参数当然不存在......有没有足够熟练的人帮帮我?真的迷路了,有点希望我的应用程序现在不在 django 中 tbh

谢谢!

【问题讨论】:

  • 它不起作用,因为您限制了 same 包。所以你说那个包需要有name'best_package''other_package',因此从你引入两个(不同)名称的那一刻起,这总是会失败。
  • 您不觉得,您应该使用or 运算符而不是and 吗?
  • @sonus21 比它还包括只有其中之一的主机
  • @WillemVanOnsem 在我的真实代码中类似于 packages_set 及其相关管理器,以访问从另一端到所选模型的所有包
  • @FilipM: 完全正确,但基本上发生的情况是它与相关的Package 模型连接一次,然后您开始在相关模型上添加WHERE 子句.

标签: python django orm django-queryset


【解决方案1】:

这不起作用的原因是因为您每次都限制同一个包。如果键是'best_package''other_package',你说应该有一个相关的包,它有name 两个'best_package''other_package',但是由于包只有一个名称,那当然会失败。

我们可以用另一种方式解决这个问题:我们首先过滤包以检索与字典中的条目匹配的所有,然后计数这些,因此检查相关包的数量是否与字典中的元素数量相同:

from django.db.models import Count, Q

pckgs_query = Q(
    *[Q(package_set__name=name, package_set__version__in=versions)
      for name, versions in pckgs_dict.items()],
    _connector=Q.OR
)

hosts = Host.objects.filter(pckgs_query).annotate(
    num_packages=Count('package_set')
).filter(
    num_packages=len(pckgs_dict)
)

因此,这将只返回安装了所有个包的Hosts,因为如果缺少一个包,那么num_packages将小于len(pckgs_dict)

【讨论】:

  • @FilikpM: 那么应该是package_set__name 等和`Count('package_set')。但这没关系。
  • 嗨,对不起,但从长远来看,这对我来说不起作用,因为我的数据库不支持从中生成的一些 sql 查询,因此我仍在寻找解决方案。
  • @FilipM:正是不支持的 SQL。它仅包含一些过滤、聚合 (COUNT) 和 HAVING 子句。据我所知,这是标准 SQL:cloud.google.com/bigquery/docs/reference/standard-sql/…
  • 由于这个问题导致我的应用程序不一致:stackoverflow.com/questions/12980038/… 因此它对我不可用
  • @FilipM:看起来package_setnameversion 的字段类型与字典中的字段类型不匹配。
猜你喜欢
  • 1970-01-01
  • 2021-10-16
  • 2021-09-27
  • 2016-11-07
  • 2014-05-07
  • 1970-01-01
  • 2018-11-27
  • 2015-12-06
  • 1970-01-01
相关资源
最近更新 更多