Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - Polymorphic Models or one big Model?

I'm currently working on a model in Django involving one model that can have a variety of different traits depending on what kind of object it is. So, let's say we have a model called Mammal, which can either be an Elephant or a Dolphin (with their own traits "tusk_length" and "flipper_length" respectively).

Basic OOP principles shout "polymorphism", and I'm inclined to agree. But, as I'm new to Django, I first want to know whether or not it is the best way to do so in Django. I've heard of plenty of examples of and some people giving their preferences toward singular giant models

I've already tried using GenericForeignKeys as described here: How can I restrict Django's GenericForeignKey to a list of models?. While this solution works beautifully, I don't like the inability to filter, and that the relationship is only one way. That is, while you can get a Dolphin from a Mammal object, you can't get the Mammal object from the Dolphin.

And so, here are my two choices:

Choice A:

from django.db import models
class Mammal(models.Model):
    hair_length = models.IntegerField()
    tusk_length = models.IntegerField()
    flipper_length = models.IntegerField()
    animal_type = models.CharField(max_length = 15, choices = ["Elephant", "Dolphin"]

Choice B:

from django.db import models
class Mammal(models.Model):
    hair_length = models.IntegerField()

class Elephant(Mammal):
    tusk_length = models.IntegerField()

class Dolphin(Mammal):
    flipper_length = models.IntegerField()

Choice B, from what I understand, has the advantage of nicer code when querying and listing all Elephants or Dolphins. However, I've noticed it's not as straightforward to get all of the Elephants from a list of Mammals (is there a query for this?) without putting animal_type in the class, with default being dependent on the class.

This leads to another problem I see with polymorphism, which won't come up in this example above or my application, but is worth mentioning is that it would be difficult to edit a Dolphin object into an Elephant without deleting the Dolphin entirely.

Overall, is there any general preference, or any big reason I shouldn't use polymorphism?

like image 803
limasxgoesto0 Avatar asked May 01 '13 00:05

limasxgoesto0


Video Answer


1 Answers

My recommendation, in general with database design, is to avoid inheritance. It complicates both the access and updates.

In Django, try using an abstract class for your base model. That means a db table will not be created for it. Its fields/columns will be auto-created in its child models. The benefit is: code reuse in Django/Python code and a simple, flat design in the database. The penalty is: it's more work to manage/query a mixed collection of child models.

See an example here: Django Patterns: Model Inheritance

Alternatively, you could change the concept of "Mammal" to "MammalTraits." And include a MammalTraits object inside each specific mammal class. In code, that is composition (has-a). In the db, that will be expressed as a foreign key.

like image 96
Bill Paetzke Avatar answered Sep 21 '22 03:09

Bill Paetzke