from django.contrib.contenttypes.models import ContentType from django.db import models from django.core.exceptions import ObjectDoesNotExist class CommentThreadManager(models.Manager): """Manager for handling comment threads on both regular and historical models.""" def for_instance(self, instance): """Get comment threads for any model instance.""" # Get the base model class if this is a historical instance if instance.__class__.__name__.startswith('Historical'): model_class = instance.instance.__class__ instance_id = instance.instance.pk else: model_class = instance.__class__ instance_id = instance.pk ct = ContentType.objects.get_for_model(model_class) return self.filter(content_type=ct, object_id=instance_id) def create_for_instance(self, instance, **kwargs): """Create a comment thread for any model instance.""" # Get the base model class if this is a historical instance if instance.__class__.__name__.startswith('Historical'): model_class = instance.instance.__class__ instance_id = instance.instance.pk else: model_class = instance.__class__ instance_id = instance.pk ct = ContentType.objects.get_for_model(model_class) return self.create(content_type=ct, object_id=instance_id, **kwargs) class ThreadedModelManager(models.Manager): """Manager for models that have comment threads.""" """Manager for models that have comment threads.""" def get_comment_threads(self, instance): """Get comment threads for this instance.""" from comments.models import CommentThread if not instance.pk: return CommentThread.objects.none() return CommentThread.objects.for_instance(instance) def add_comment_thread(self, instance, **kwargs): """Create a comment thread for this instance.""" from comments.models import CommentThread if not instance.pk: raise ObjectDoesNotExist("Cannot create comment thread for unsaved instance") return CommentThread.objects.create_for_instance(instance, **kwargs) def with_comment_threads(self): """Get all instances with their comment threads.""" from comments.models import CommentThread qs = self.get_queryset() content_type = ContentType.objects.get_for_model(self.model) # Get comment threads through a subquery threads = CommentThread.objects.filter( content_type=content_type, object_id=models.OuterRef('pk') ) return qs.annotate( comment_count=models.Subquery( threads.values('object_id') .annotate(count=models.Count('id')) .values('count'), output_field=models.IntegerField() ) )