I’m getting stuck on a complex query, trying to use Django’s 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()
The gist of this is, Products have multiple Versions. Some of these Versions are ‘special’ – we keep track of this by making a SpecialVersion object pointing to the ‘special’ Version object. When we create a non-special version, it must indicate a compatibility with a SpecialVersion. That is, starting at the SpecialVersion indicated by compatible_from. A Product can become deprecated at a certain special version.
Now, I want to be able to find appropriate Products given a certain SpecialVersion. In other words, I want to get all Product objects where there is a Version available that has a SpecialVersion below my given SpecialVersion. Furthermore, the Product’s deprecated SpecialVersion must be either null, or below the given SpecialVersion if not null.
TL;DR:
Select all Products where the given SpecialVersion is in the range between the lowest compatible_from SpecialVersion in the product, and the deprecated SpecialVersion (if this exists).
EDIT: Example.
Products
id | deprecated
0 | None
1 | 2
Versions
id | prd | compat
0 | 0 | 1
1 | 0 | 2
2 | 1 | 2
SpecialVersions
id | ver | ord
0 | Null | 1
1 | Null | 2
2 | Null | 3
3 | Null | 4
A query for compatibility w/ SpecialVersion would return no products, because none of the products have versions that specify a compatibility as low as that. A query for compat w/ SpecialVersion would return all of the Products because they both have compatibility starting at SpecialVersion id=1 and id=2, respectively. Finally, a query for compat w/ SpecialVersion would return ONLY the product id=0 because though both products have a SpecialVersion compat low enough, the second product has been deprecated for SpecialVersions and upwards.
Here is what I ended up using: