4

I'm trying to emulate an inheritance model using django's generic relations. So far, this is what I've come up with:

class Base(models.Model):
  content_type = models.ForeignKey(ContentType)
  object_id = models.PositiveIntegerField()
  content_object = generic.GenericForeignKey()
  ... other stuff

  class Meta:
    unique_together = ("content_type", "object_id")

class SubClass1(models.Model):
  ... properties for this class

  _base = generic.GenericRelation(Base)

  @property
  def base(self):
    return self._base.all()[0]

From what you can see here (hopefully, at least), the SubClass1 should have a one-to-one relationship with Base, which is why I went through all the work of creating that _base field and then covering it with the base property. Having that generic relation will automagically wire up cascading deletes, which is what I want (and I have a post-delete signal that will wire up the delete from the other direction).

There could be any number of subclasses off of Base, and the thing that makes me feel gross is having to copy&paste the _base and its covering property. I've also got a custom object manager that goes with this, and potentially other things that essentially should all behave the same within each subclass of Base.

Is there a good way to go about encapsulating this common functionality so I don't have to copy&paste it for each sub class?

DMac the Destroyer
  • 5,240
  • 6
  • 36
  • 56

1 Answers1

2

Why not have a BaseSubClass, and then inherit from that. So based on your example:

class BaseSubClass(models.Model):
    _base = generic.GenericRelation(Base)

    class Meta:
        abstract = True

    @property
    def base(self):
      return self._base.all()[0]

class SubClass1(BaseSubClass):
    # fields
Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • I initially did this, but didn't like the way the models framework built up the database... then while I was bulding up an example to explain why I wouldn't accept your answer I remembered about abstract base classes and added the `abstract = True` attribute in the `Meta` class, and it looks perfect! – DMac the Destroyer Oct 04 '11 at 04:31
  • You're right. I actually intended to add `abstract = True` but then completely forgot. I updated my answer above accordingly. – Chris Pratt Oct 04 '11 at 14:16