[Fixed]-Django model subclassing approaches

12πŸ‘

βœ…

I’ve pondered about both answers and came up with something based off of those suggestions. Thus I’m adding this answer of my own.

I’ve chosen to use django-polymorphic, quite nice tool suggested by @professorDante. Since this is a multi-table inheritance, @albar’s answer is also somewhat correct.

tl;dr

django-polymorphic attends the 3 main requirements:

  1. Allow django ORM querying style
  2. Keep db level constraints by having a multi-table inheritance and one table for each sub class
  3. Easy django admin integration

Longer version

Django-polymorphic allows me to query all different event instances from the base class, like:

# assuming the objects where previously created
>>> Event.objects.all()
[<SubEventA object>, <SubEventB object>, <SubEventC object>]

It also has great django admin integration, allowing seamless objects creation and editing.

The models using django-polymorphic would look like:

# A.models.py
from polymorphic import PolymorphicModel

class Event(PolymorphicModel):
    commom_field = models.BooleanField()

    # no longer abstract

class SubEventA(Event):
    email = models.EmailField(unique=True)

class SubEventB(Event):
    title = models.TextField()

class SubEventC(Event):
    number = models.IntegerField(default=10)



# B.models.py

# it doesnt have to be polymorphic to reference polymorphic models
class OtherModel(models.Model):
    event = models.ForeignKey('A.Event')

Besides, I can reference only the base model from another class and I can assign any of the subclasses directly, such as:

>>> sub_event_b = SubEventB.objects.create(title='what a lovely day')
>>> other_model = OtherModel()
>>> other_model.event = sub_event_b
πŸ‘€alfetopito

4πŸ‘

My .2c on this. Not sure about your design in #3. Each SubEvent subclasses Event, and has a one-to-one to Event? Isn’t that the same thing?

Your proposal on the Generic Key is exactly what it is designed for.

Another possibility – Polymorphism with Mixins. Use something like Django-polymorphic, so querying returns you the subclass you want. I use this all the time and its super useful. Then make Mixins for attributes that will be reused across many classes. So a simple example, making an email Mixin

class EmailMixin(models.Model):

    email = models.EmailField(unique=True)

    class Meta:
        abstract = True

Then use it

class MySubEvent(EmailMixin, models.Model):

    <do stuff>

This way you dont have redundant attributes on subclasses, as you would if they were all in the parent.

2πŸ‘

Why not a multi-table inheritance?

class Event(models.Model):
    commom_field = models.BooleanField()

class SubEventA(Event):
    email = models.EmailField(unique=True)

class SubEventB(Event):
    title = models.TextField(blank=True)

class SubEventC(Event):
    number = models.IntegerField(default=10)
πŸ‘€albar

Leave a comment