djangoabstract-class

How to query abstract-class-based objects in Django?


Let's say I have an abstract base class that looks like this:

class StellarObject(BaseModel):
  title = models.CharField(max_length=255)
  description = models.TextField()
  slug = models.SlugField(blank=True, null=True)

  class Meta:
    abstract = True

Now, let's say I have two actual database classes that inherit from StellarObject

class Planet(StellarObject):
  type = models.CharField(max_length=50)
  size = models.IntegerField(max_length=10)

class Star(StellarObject):
  mass = models.IntegerField(max_length=10)

So far, so good. If I want to get Planets or Stars, all I do is this:

Thing.objects.all() #or
Thing.objects.filter() #or count(), etc...

But what if I want to get ALL StellarObjects? If I do:

StellarObject.objects.all()

It of course returns an error, because an abstract class isn't an actual database object, and therefore cannot be queried. Everything I've read says I need to do two queries, one each on Planets and Stars, and then merge them. That seems horribly inefficient. Is that the only way?


Solution

  • At its root, this is part of the mismatch between objects and relational databases. The ORM does a great job in abstracting out the differences, but sometimes you just come up against them anyway.

    Basically, you have to choose between abstract inheritance, in which case there is no database relationship between the two classes, or multi-table inheritance, which keeps the database relationship at a cost of efficiency (an extra database join) for each query.