Managing Multiple Django Models Under a Common Interface

A simple example how to manage content with common data in Django
January 29, 2025 by
Managing Multiple Django Models Under a Common Interface
Hamed Mohammadi
| No comments yet

When building a Django application, you may have multiple models that share common fields and functionalities. A common challenge is how to iterate over all instances of these models in a unified way. This blog post will guide you through creating a structured approach using Django’s model inheritance and ContentType framework.

Defining a Common Base Model

To avoid redundancy and promote code reusability, we can create an abstract base model that all other content models will inherit from:

from django.db import models
from django.contrib.auth.models import User

class BaseContent(models.Model):
    title = models.CharField(max_length=255)
    content = models.TextField(blank=True, null=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True  # This makes it an abstract model

With this structure, we can now define specific content types like Post, Poem, and Prose by inheriting from BaseContent.

Implementing the Content Models

Each subclass of BaseContent will contain fields unique to that content type:

class Post(BaseContent):
    category = models.CharField(max_length=100, blank=True, null=True)

    def __str__(self):
        return f"Post: {self.title}"

class Poem(BaseContent):
    meter = models.CharField(max_length=255, blank=True, null=True)

    def __str__(self):
        return f"Poem: {self.title}"

class Prose(BaseContent):
    genre = models.CharField(max_length=100, blank=True, null=True)

    def __str__(self):
        return f"Prose: {self.title}"

At this stage, each model can be queried individually, but there’s no direct way to iterate over all instances together.

Unifying Queries with ContentType Framework

To query all content types together, we can use Django’s ContentType and GenericForeignKey to create a universal index model:

from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey

class ContentIndex(models.Model):
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey("content_type", "object_id")
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return str(self.content_object)

Automatically Indexing Content

To ensure every new Post, Poem, and Prose entry gets indexed, we can use Django signals:

from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=Post)
@receiver(post_save, sender=Poem)
@receiver(post_save, sender=Prose)
def add_to_content_index(sender, instance, **kwargs):
    ContentIndex.objects.get_or_create(
        content_type=ContentType.objects.get_for_model(instance),
        object_id=instance.id,
        content_object=instance
    )

This ensures that every time a new instance of Post, Poem, or Prose is created, it gets added to ContentIndex automatically.

Querying All Content Together

Now, we can retrieve all content objects with a single query:

all_content = ContentIndex.objects.select_related("content_type", "content_object")

for item in all_content:
    print(item.content_object.title, "-", item.content_object.__class__.__name__)


This approach allows you to: ✅ Avoid redundancy by using a common base model. ✅ Dynamically track all content types in one place. ✅ Retrieve all content types in a single loop. ✅ Easily expand your system by adding new content models without modifying query logic.

Conclusion

By combining Django’s model inheritance with the ContentType framework, we achieve an elegant and scalable solution for managing multiple content types under a unified system. This method is particularly useful for content-driven applications, blogs, and publishing platforms where different types of posts need to be accessed together.

Would you like to see how to extend this solution with additional filters or API endpoints? Let me know in the comments!

Managing Multiple Django Models Under a Common Interface
Hamed Mohammadi January 29, 2025
Share this post
Tags
Archive

Please visit our blog at:

https://zehabsd.com/blog

A platform for Flash Stories:

https://readflashy.com

A platform for Persian Literature Lovers:

https://sarayesokhan.com

Sign in to leave a comment