python / expert
Snippet
Django ContentType Framework for Generic Relations
Django's ContentType framework enables generic relations, allowing a single Comment model to attach to any other model without creating separate foreign keys. This is ideal for building reusable components like comments, tags, or likes. The GenericRelation on the target models enables reverse lookups, while the compound index on content_type and object_id ensures efficient querying.
snippet.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from django.db import modelsfrom django.contrib.contenttypes.models import ContentTypefrom django.contrib.contenttypes.fields import GenericForeignKey, GenericRelationclass Comment(models.Model):content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)object_id = models.PositiveIntegerField()content_object = GenericForeignKey('content_type', 'object_id')text = models.TextField()created_at = models.DateTimeField(auto_now_add=True)class Meta:indexes = [models.Index(fields=['content_type', 'object_id']),]class Article(models.Model):title = models.CharField(max_length=200)body = models.TextField()comments = GenericRelation(Comment, related_query_name='articles')class Product(models.Model):name = models.CharField(max_length=200)price = models.DecimalField(max_digits=10, decimal_places=2)comments = GenericRelation(Comment, related_query_name='products')# Usage exampledef get_recent_comments(obj, limit=5):content_type = ContentType.objects.get_for_model(obj)return Comment.objects.filter(content_type=content_type,object_id=obj.pk).order_by('-created_at')[:limit]
django
Breakdown
1
content_type = models.ForeignKey(ContentType, ...)
Stores which model class the comment is attached to
2
object_id = models.PositiveIntegerField()
Stores the primary key of the related object
3
GenericForeignKey('content_type', 'object_id')
Dynamically resolves to the actual related object at runtime
4
GenericRelation(Comment, related_query_name='articles')
Enables Article.comments.all() and Comment.objects.filter(articles=article)
5
ContentType.objects.get_for_model(obj)
Retrieves the ContentType instance for any Django model dynamically
6
models.Index(fields=['content_type', 'object_id'])
Composite index for fast lookups when filtering by content type and ID