我遇到了复杂的查询,试图使用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对象,其中有一个Version可用,其SpecialVersion低于我给定的SpecialVersion。此外,Product弃用的SpecialVersion必须为null,或者如果不为null,则必须低于给定的SpecialVersion。
TL; DR: 选择给定SpecialVersion在产品中最低的compatible_from SpecialVersion和已弃用的SpecialVersion(如果存在)之间的范围内的所有产品。
编辑:示例。
产品
id |弃用
0 |无
1 | 2个
版本
id | prd | COMPAT
0 | 0 | 1
1 | 0 | 2
2 | 1 | 2个
SpecialVersions
id | ver | ORD
0 |空| 1
1 |空| 2
2 |空| 3
3 |空| 4个
对于兼容性w / SpecialVersion的查询将不返回任何产品,因为没有产品具有指定兼容性低的版本。对Compat w / SpecialVersion的查询将返回所有产品,因为它们都具有从SpecialVersion id = 1和id = 2开始的兼容性。最后,对compat w / SpecialVersion的查询将仅返回产品id = 0,因为虽然两个产品的SpecialVersion compat足够低,但第二个产品已被弃用于SpecialVersions及以上。
答案 0 :(得分:0)
我相信你所寻找的是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 是您从代码中的其他位置收到的版本顺序。
答案 1 :(得分:0)
以下是我最终使用的内容:
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))