5

I'm using django-model-utils inheritance manager to query a data model with multi-table inheritance and it mostly works great! What doesn't work great is when I want to .select_subclasses() but also filter for a specific subclass. For example:

class Salad:
    ...

class Vegetable:
    salad = models.ForeignKey(Salad)
    ...

class Cucumber(Vegetable):
    ...

class Carrot(Vegetable):
    ...

I would love to be able to just get ONLY all of the Cucumber objects related to a specific Salad without any Carrot objects. Unfortunately, the docs don't appear to explain this. Is my best option to create a type field on the Vegetable class that I set when saving any Vegetable object that would then be available for "regular" filtering? Thanks in advance!

TheCatParty
  • 1,449
  • 12
  • 19

2 Answers2

10

If you want to filter only Cucumber objects you could do something like this:

Vegetable.objects.exclude(cucumber__isnull=True)
ilse2005
  • 11,189
  • 5
  • 51
  • 75
  • This _maybe_ works, but isn't a very scalable solution when there are potentially MANY classes that extend Vegetable. Any classes that are created afterward that extend Vegetable will 'break' any existing queries that rely on filtering on `cucumber__isnull=True`. Can you think of another alternative? – TheCatParty Feb 27 '16 at 15:38
  • Why should this break if you create new classes extending Vegetable? – ilse2005 Feb 27 '16 at 15:40
  • 1
    Oh! I think I misunderstood. I'l give this a shot soon - thank you! – TheCatParty Feb 27 '16 at 15:44
  • 1
    This worked perfectly. Marking as the correct answer. Relatedly, can you think of a way to not only filter for a specific subclass, but also filter on a field on that specific subclass in the same query? For example, if I only wanted `Cucumber` objects with a length greater than 12 centimeters. – TheCatParty Feb 29 '16 at 14:43
  • Thanks! `Vegetable.objects.exclude(cucumber__isnull=True).filter(cucumber__length__gte=12)` should work. – ilse2005 Feb 29 '16 at 14:57
0

You can use .select_subclasses(Cucumber) which would return the Cucumber objects and the rest as Vegetable objects. You could later filter it out using the isinstance

Akram Parvez
  • 451
  • 3
  • 8
  • Unfortunately, this doesn't really answer the question. Because there may be MANY vegetable objects, it's far more efficient to filter at the query instead of afterward. – TheCatParty Feb 27 '16 at 15:36