【问题标题】:Complex query (django ORM or SQL)复杂查询(django ORM 或 SQL)
【发布时间】:2012-08-03 15:02:34
【问题描述】:

我遇到了一个复杂的查询,试图使用 Django 的 ORM。

models.py

class Product(models.Model):
    deprecated = models.ForeignKey(SpecialVersion, null=True)

class Version(models.Model):
    compatible_from = models.ForeignKey(SpecialVersion)
    product = models.ForeignKey(Product)

class SpecialVersion(models.Model):
    version = models.ForeignKey(Version, null=True)
    order = models.IntegerField()

要点是,产品有多个版本。其中一些版本是“特殊的”——我们通过创建一个指向“特殊”版本对象的 SpecialVersion 对象来跟踪这一点。当我们创建非特殊版本时,它必须表明与 SpecialVersion 的兼容性。也就是说,从 compatible_from 指示的 SpecialVersion 开始。产品可能会在某个特殊版本中被弃用。

现在,我希望能够在给定特定 SpecialVersion 的情况下找到合适的产品。换句话说,我想获取所有 Product 对象,其中有一个可用的版本,其 SpecialVersion 低于我给定的 SpecialVersion。此外,产品的弃用 SpecialVersion 必须为 null,或者如果不为 null,则低于给定的 SpecialVersion。

TL;DR: 选择给定 SpecialVersion 介于产品中最低 compatible_from SpecialVersion 和已弃用 SpecialVersion(如果存在)之间的所有产品。

编辑:示例。

产品
编号 |已弃用
0 |无
1 | 2

版本
编号 |珠三角 |兼容
0 | 0 | 1
1 | 0 | 2
2 | 1 | 2

特别版
编号 |版本 |排序
0 |空 | 1
1 |空 | 2
2 |空 | 3
3 |空 | 4

查询与 SpecialVersion 的兼容性将不会返回任何产品,因为没有任何产品具有指定低兼容性的版本。查询 compat w/SpecialVersion 将返回所有产品,因为它们都具有分别从 SpecialVersion id=1 和 id=2 开始的兼容性。最后,查询 compat w/SpecialVersion 将仅返回产品 id=0,因为尽管这两个产品的 SpecialVersion 兼容性足够低,但对于 SpecialVersions 及更高版本,第二个产品已被弃用。

【问题讨论】:

  • 您能否提供一些虚假数据并显示您希望根据示例请求选择哪些行?
  • 我让 SpecialVersions 有一个空版本字段,因为那个位无关紧要。

标签: sql django orm


【解决方案1】:

我相信您正在寻找的是Django Q Object。这允许您在查询中使用复杂的查找,例如“OR”语句。如果我正确理解了您的问题,那么类似的内容应该可以正常工作:

from django.db.models import Q
models.Product.objects.filter(Q(deprecated__isnull=True) | Q(version__compatible_from__order__lte=GIVENSPECIALVERSION)).all()

GIVENSPECIALVERSION 是您从代码中其他地方收到的版本顺序。

【讨论】:

  • 关闭,但不完全——我需要检查是否被弃用(即——如果不为空,则确保我低于弃用的版本)。此外,没有版本字段 - 它是一个外键,因此您只能获得需要注释的版本集。请参阅下面的答案。
  • @guywhoneedsahand 啊,明白了。试图将我的头脑围绕您的设置。很高兴你成功了!
  • 是的,这有点令人费解。谢谢。
【解决方案2】:

这是我最终使用的:

products = Product.objects.annotate(min_version=Min(version_set__compatible_from__order)).filter(min_version__lte = given_special_version).filter(Q(deprecated__isnull = True) | Q(deprecated__order__gt = given_special_version))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-09
    • 1970-01-01
    • 2021-09-07
    • 2021-05-27
    • 2018-05-15
    • 2019-08-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多