Context
I am in the process of modeling my data using Django models.
The main model is an Article
. It holds the actual content.
Then each Article
must be attached to a group of articles. Those group may be a Blog
, a Category
a Portfolio
or a Story
. Every Article
must be attached to one, and exactly one of those. That is, either a blog, a category or a story. Those models have very different fields and features.
I thought of three ways to reach that goal (and a bonus one that really looks wrong).
Option #1: A generic foreign key
As in django.contrib.contenttypes.fields.GenericForeignKey
. It would look like this:
class Category(Model):
# some fields
class Blog(Model):
# some fields
class Article(Model):
group_type = ForeignKey(ContentType)
group_id = PositiveIntegerField()
group = GenericForeignKey('group_type', 'group_id')
# some fields
On the database side, that means no relation actually exists between the models, they are enforced by Django.
Option #2: Multitable inheritance
Make article groups all inherit from an ArticleGroup
model. This would look like this:
class ArticleGroup(Model):
group_type = ForeignKey(ContentType)
class Category(ArticleGroup):
# some fields
class Blog(ArticleGroup):
# some fields
class Article(Model):
group = ForeignKey(ArticleGroup)
# some fields
On the database side, this creates an additional table for ArticleGroup
, then Category
and Blog
have an implicit foreign key to that table as their primary key.
Sidenote: I know there is a package that automates the bookkeeping of such constructions.
Option #3: manual OneToOneFields
On the database side, it is equivalent to option #2. But in the code, all relations are made explicit:
class ArticleGroup(Model):
group_type = ForeignKey(ContentType)
class Category(Model):
id = OneToOneField(ArticleGroup, primary_key=True)
# some fields
class Blog(Model):
id = OneToOneField(ArticleGroup, primary_key=True)
# some fields
class Article(Model):
group = ForeignKey(ArticleGroup)
# some fields
I don't really see what the point of that would be, apart from making explicit what Django's inheritance magic implicitly does.
Bonus: multicolumn
It seems pretty dirty so I just add it as a bonus, but it would also be possible to define a nullable ForeignKey to each of Category
, Blog
, ... directly on the Article
model.
So...
...I cannot really decide between those. What are the pros and cons of each approach? Are there some best practices? Did I miss a better approach?
If that matters, I'm using Django 1.8.