Files
thrillwiki_django_no_react/comments/models.py

119 lines
3.8 KiB
Python

from django.db import models
from django.conf import settings
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from .managers import CommentThreadManager, ThreadedModelManager
class CommentThread(models.Model):
"""
A thread of comments that can be attached to any model instance,
including historical versions.
"""
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
title = models.CharField(max_length=255, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
created_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
null=True,
related_name='created_comment_threads'
)
is_locked = models.BooleanField(default=False)
is_hidden = models.BooleanField(default=False)
objects = CommentThreadManager()
class Meta:
indexes = [
models.Index(fields=['content_type', 'object_id']),
]
ordering = ['-created_at']
def __str__(self):
return f"Comment Thread on {self.content_object} - {self.title}"
class CommentThreads:
"""
Helper class to manage comment threads for a model instance.
This is used instead of direct inheritance to avoid historical model issues.
"""
def __init__(self, instance):
self.instance = instance
self._info = {}
def get_info(self):
"""Get or compute comment thread information."""
if not self._info:
ct = ContentType.objects.get_for_model(self.instance.__class__)
self._info = {
'count': CommentThread.objects.filter(
content_type=ct,
object_id=self.instance.pk
).count(),
'content_type': ct,
'object_id': self.instance.pk
}
return self._info
def get_threads(self):
"""Get comment threads for this instance."""
info = self.get_info()
return CommentThread.objects.filter(
content_type=info['content_type'],
object_id=info['object_id']
)
def add_thread(self, title='', created_by=None):
"""Create a new comment thread for this instance."""
info = self.get_info()
thread = CommentThread.objects.create(
content_type=info['content_type'],
object_id=info['object_id'],
title=title,
created_by=created_by
)
self._info = {} # Clear cache
return thread
def get_comment_threads(instance):
"""Get or create a CommentThreads helper for a model instance."""
if not hasattr(instance, '_comment_threads'):
instance._comment_threads = CommentThreads(instance)
return instance._comment_threads
class Comment(models.Model):
"""Individual comment within a thread."""
thread = models.ForeignKey(
CommentThread,
on_delete=models.CASCADE,
related_name='comments'
)
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
null=True,
related_name='comments'
)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
is_edited = models.BooleanField(default=False)
is_hidden = models.BooleanField(default=False)
parent = models.ForeignKey(
'self',
on_delete=models.CASCADE,
null=True,
blank=True,
related_name='replies'
)
class Meta:
ordering = ['created_at']
def __str__(self):
return f"Comment by {self.author} on {self.created_at}"