##// END OF EJS Templates
Merged with default branch
Merged with default branch

File last commit:

r718:056bdb08 default
r847:011dea60 merge decentral
Show More
thread.py
187 lines | 5.2 KiB | text/x-python | PythonLexer
neko259
Moved thread model to a separate module
r691 import logging
neko259
Moved post image to a separate model. Each post (as of model) can contain multiple images now. The image shown to the user is got with get_first_image method
r693 from django.db.models import Count
neko259
Moved thread model to a separate module
r691 from django.utils import timezone
from django.core.cache import cache
from django.db import models
neko259
Moved imageboard settings to the boards settings module. Added setting to disable archive
r716 from boards import settings
neko259
Moved thread model to a separate module
r691
__author__ = 'neko259'
logger = logging.getLogger(__name__)
CACHE_KEY_OPENING_POST = 'opening_post_id'
neko259
Code cleanup. Update only edited fields while performing thread archiving or post editing. Remove image when post is removed
r715 class ThreadManager(models.Manager):
neko259
Moved imageboard settings to the boards settings module. Added setting to disable archive
r716 def process_oldest_threads(self):
neko259
Code cleanup. Update only edited fields while performing thread archiving or post editing. Remove image when post is removed
r715 """
Preserves maximum thread count. If there are too many threads,
neko259
Moved imageboard settings to the boards settings module. Added setting to disable archive
r716 archive or delete the old ones.
neko259
Code cleanup. Update only edited fields while performing thread archiving or post editing. Remove image when post is removed
r715 """
threads = Thread.objects.filter(archived=False).order_by('-bump_time')
thread_count = threads.count()
if thread_count > settings.MAX_THREAD_COUNT:
num_threads_to_delete = thread_count - settings.MAX_THREAD_COUNT
old_threads = threads[thread_count - num_threads_to_delete:]
for thread in old_threads:
neko259
Moved imageboard settings to the boards settings module. Added setting to disable archive
r716 if settings.ARCHIVE_THREADS:
self._archive_thread(thread)
else:
neko259
Use own search form and view
r718 thread.delete()
neko259
Moved imageboard settings to the boards settings module. Added setting to disable archive
r716
logger.info('Processed %d old threads' % num_threads_to_delete)
neko259
Code cleanup. Update only edited fields while performing thread archiving or post editing. Remove image when post is removed
r715
neko259
Moved imageboard settings to the boards settings module. Added setting to disable archive
r716 def _archive_thread(self, thread):
thread.archived = True
thread.last_edit_time = timezone.now()
thread.save(update_fields=['archived', 'last_edit_time'])
neko259
Code cleanup. Update only edited fields while performing thread archiving or post editing. Remove image when post is removed
r715
neko259
Moved thread model to a separate module
r691 class Thread(models.Model):
neko259
Code cleanup. Update only edited fields while performing thread archiving or post editing. Remove image when post is removed
r715 objects = ThreadManager()
neko259
Moved thread model to a separate module
r691
class Meta:
app_label = 'boards'
tags = models.ManyToManyField('Tag')
bump_time = models.DateTimeField()
last_edit_time = models.DateTimeField()
replies = models.ManyToManyField('Post', symmetrical=False, null=True,
blank=True, related_name='tre+')
archived = models.BooleanField(default=False)
def get_tags(self):
"""
Gets a sorted tag list.
"""
return self.tags.order_by('name')
def bump(self):
"""
Bumps (moves to up) thread if possible.
"""
if self.can_bump():
self.bump_time = timezone.now()
logger.info('Bumped thread %d' % self.id)
def get_reply_count(self):
return self.replies.count()
def get_images_count(self):
neko259
Moved post image to a separate model. Each post (as of model) can contain multiple images now. The image shown to the user is got with get_first_image method
r693 # TODO Use sum
total_count = 0
for post_with_image in self.replies.annotate(images_count=Count(
'images')):
total_count += post_with_image.images_count
return total_count
neko259
Moved thread model to a separate module
r691
def can_bump(self):
"""
Checks if the thread can be bumped by replying to it.
"""
if self.archived:
return False
post_count = self.get_reply_count()
return post_count < settings.MAX_POSTS_PER_THREAD
def get_last_replies(self):
"""
Gets several last replies, not including opening post
"""
if settings.LAST_REPLIES_COUNT > 0:
reply_count = self.get_reply_count()
if reply_count > 0:
reply_count_to_show = min(settings.LAST_REPLIES_COUNT,
reply_count - 1)
neko259
Optimized loading post images in post template
r694 replies = self.get_replies()
neko259
Moved thread model to a separate module
r691 last_replies = replies[reply_count - reply_count_to_show:]
return last_replies
def get_skipped_replies_count(self):
"""
Gets number of posts between opening post and last replies.
"""
reply_count = self.get_reply_count()
last_replies_count = min(settings.LAST_REPLIES_COUNT,
reply_count - 1)
return reply_count - last_replies_count - 1
def get_replies(self, view_fields_only=False):
"""
Gets sorted thread posts
"""
neko259
Optimized loading post images in post template
r694 query = self.replies.order_by('pub_time').prefetch_related('images')
neko259
Moved thread model to a separate module
r691 if view_fields_only:
neko259
Moved post image to a separate model. Each post (as of model) can contain multiple images now. The image shown to the user is got with get_first_image method
r693 query = query.defer('poster_user_agent', 'text_markup_type')
neko259
Moved thread model to a separate module
r691 return query.all()
neko259
Moved post image to a separate model. Each post (as of model) can contain multiple images now. The image shown to the user is got with get_first_image method
r693 def get_replies_with_images(self, view_fields_only=False):
return self.get_replies(view_fields_only).annotate(images_count=Count(
'images')).filter(images_count__gt=0)
neko259
Moved thread model to a separate module
r691 def add_tag(self, tag):
"""
Connects thread to a tag and tag to a thread
"""
self.tags.add(tag)
tag.threads.add(self)
def remove_tag(self, tag):
self.tags.remove(tag)
tag.threads.remove(self)
def get_opening_post(self, only_id=False):
"""
Gets the first post of the thread
"""
query = self.replies.order_by('pub_time')
if only_id:
query = query.only('id')
opening_post = query.first()
return opening_post
def get_opening_post_id(self):
"""
Gets ID of the first thread post.
"""
cache_key = CACHE_KEY_OPENING_POST + str(self.id)
opening_post_id = cache.get(cache_key)
if not opening_post_id:
opening_post_id = self.get_opening_post(only_id=True).id
cache.set(cache_key, opening_post_id)
return opening_post_id
def __unicode__(self):
return str(self.id)
def get_pub_time(self):
"""
Gets opening post's pub time because thread does not have its own one.
"""
neko259
Optimized loading post images in post template
r694 return self.get_opening_post().pub_time
neko259
Use own search form and view
r718
def delete(self, using=None):
if self.replies.exists():
self.replies.all().delete()
super(Thread, self).delete(using)