Okay, here's a challenge, Djangonistas!
My let's say my project has 3 types of data.
- Project
- Audio
- Video
Projects can have references to an unlimited number of Video and Audio objects, as well as unlimited references to other Projects.
What is the best way to model this? It must be done in a generic way such that new object types can be added in the future (Images, Links, Smells, etc.), and such that objects can be referenced by multiple Projects.
I have 3 theories on how to do this.
#1: Inheritance
Create a BaseModel class and have all other objects inherit from it.
class BaseModel(models.Model)
class Project(BaseModel)
class Video(BaseModel)
etc
then, have a ManyToMany field to all BaseModels inside of the Project class.
class Project(BaseModel):
content = models.ManyToManyField(BaseModel)
Will this work and be performant?
#2: Generic Foreign Keys
I could also set up system which would use a GenericForeignKey field which could use the ContentTypes framework
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
(I think this is probably the worst idea.)
#3: Generic ManytoMany Keys
Finally, I could have a separate table which maintained all of the relationships between objects.
class RelatedObject(models.Model):
"""
A generic many-to-many implementation where diverse objects are related
across a single model to other diverse objects -> using a dual GFK
"""
# SOURCE OBJECT:
parent_type = models.ForeignKey(ContentType, related_name="child_%(class)s")
parent_id = models.IntegerField(db_index=True)
parent = GenericForeignKey(ct_field="parent_type", fk_field="parent_id")
# ACTUAL RELATED OBJECT:
object_type = models.ForeignKey(ContentType, related_name="related_%(class)s")
object_id = models.IntegerField(db_index=True)
object = GenericForeignKey(ct_field="object_type", fk_field="object_id")
alias = models.CharField(max_length=255, blank=True)
creation_date = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-creation_date',)
def __unicode__(self):
return '%s related to %s ("%s")' % (self.parent, self.object, self.alias)
and then
class Project(models.Model):
related = RelatedObjectsDescriptor()
This is laid out in greater detail by Charles Leifer here: http://charlesleifer.com/blog/connecting-anything-to-anything-with-django/ and his django-generic-m2m project: https://github.com/coleifer/django-generic-m2m
What to do?
So, what are the pros and cons of each of these approaches to storing relationships? Which is the fastest, which is the easier to write and maintain? What approaches have you used in the past?
Thanks very much!