0 Tage Serie
python / expert
Snippet

Django ContentType-Framework für generische Beziehungen

Djangos ContentType-Framework ermöglicht generische Beziehungen und erlaubt einem einzelnen Comment-Modell, sich an jedes andere Modell anzuhängen, ohne separate Fremdschlüssel zu erstellen. Dies ist ideal für den Aufbau wiederverwendbarer Komponenten wie Kommentare, Tags oder Likes. Die GenericRelation an den Zielmodellen ermöglicht umgekehrte Lookups, während der zusammengesetzte Index auf content_type und object_id effizientes Abfragen gewährleistet.

snippet.py
python
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 models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
class 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 example
def 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
Erklärung
1
content_type = models.ForeignKey(ContentType, ...)
Speichert, welche Modellklasse der Kommentar zugeordnet ist
2
object_id = models.PositiveIntegerField()
Speichert den Primärschlüssel des zugehörigen Objekts
3
GenericForeignKey('content_type', 'object_id')
Löst zur Laufzeit dynamisch zum tatsächlichen zugehörigen Objekt auf
4
GenericRelation(Comment, related_query_name='articles')
Ermöglicht Article.comments.all() und Comment.objects.filter(articles=article)
5
ContentType.objects.get_for_model(obj)
Ruft die ContentType-Instanz für ein beliebiges Django-Modell dynamisch ab
6
models.Index(fields=['content_type', 'object_id'])
Zusammengesetzter Index für schnelle Lookups beim Filtern nach Inhaltstyp und ID