python / expert
Snippet
Django ContentTypes Framework for Generic Relations
Django's ContentTypes framework enables generic relationships allowing a single model to reference any other model in the system. This is ideal for tagging systems, comments, or any scenario where you need flexible foreign key relationships without creating multiple foreign key columns. The GenericForeignKey works with two columns: content_type stores the model type and object_id stores the primary key of the referenced object.
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
from django.db import modelsfrom django.contrib.contenttypes.models import ContentTypefrom django.contrib.contenttypes.fields import GenericForeignKey, GenericRelationclass TaggedItem(models.Model):tag = models.CharField(max_length=100)content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)object_id = models.PositiveIntegerField()content_object = GenericForeignKey('content_type', 'object_id')class Meta:indexes = [models.Index(fields=['content_type', 'object_id']),]class Article(models.Model):title = models.CharField(max_length=200)tags = GenericRelation(TaggedItem, related_query_name='articles')class Product(models.Model):name = models.CharField(max_length=200)tags = GenericRelation(TaggedItem)def get_objects_by_tag(tag_name):content_type = ContentType.objects.get_for_model(Article)return TaggedItem.objects.filter(tag=tag_name,content_type=content_type).select_related('content_object')def get_all_tags_for_object(obj):return obj.tags.all() if hasattr(obj, 'tags') else []
django
Breakdown
1
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
Imports generic relationship field classes from ContentTypes app
2
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
Stores reference to the target model's ContentType record
3
object_id = models.PositiveIntegerField()
Stores the PK of the linked object (supports any integer PK)
4
GenericRelation(TaggedItem, related_query_name='articles')
Creates reverse accessor enabling Article.tags.all() queries
5
ContentType.objects.get_for_model(Article)
Retrieves the ContentType instance for the Article model dynamically
6
models.Index(fields=['content_type', 'object_id'])
Composite index optimizes GenericForeignKey lookups