##// END OF EJS Templates
Small refactoring of threads view
Small refactoring of threads view

File last commit:

r1347:239fa253 default
r1374:e531c1da default
Show More
thread.py
258 lines | 7.9 KiB | text/x-python | PythonLexer
neko259
Moved thread model to a separate module
r691 import logging
neko259
Refactored websockets notifications and updating threads when updating posts
r1088 from adjacent import Client
neko259
Started work on the method caching decorator (BB-57)
r957
neko259
Faster way of obtaining new post count
r1345 from django.db.models import Count, Sum, QuerySet, Q
neko259
Moved thread model to a separate module
r691 from django.utils import timezone
from django.db import models
neko259
Started work on the method caching decorator (BB-57)
r957
neko259
Moved imageboard settings to the boards settings module. Added setting to disable archive
r716 from boards import settings
neko259
Refactoring
r1027 import boards
neko259
Added ability to cache method result with additional arguments. Cache thread...
r1106 from boards.utils import cached_result, datetime_to_epoch
neko259
Removed unecessary connection of a thread to its replies, cause posts are...
r958 from boards.models.post import Post
neko259
Added type hints to some models and managers
r1083 from boards.models.tag import Tag
neko259
Started work on the method caching decorator (BB-57)
r957
neko259
Fixed last post link in new favorite posts api
r1346 FAV_THREAD_NO_UPDATES = -1
neko259
Moved thread model to a separate module
r691
__author__ = 'neko259'
logger = logging.getLogger(__name__)
neko259
Refactored websockets notifications and updating threads when updating posts
r1088 WS_NOTIFICATION_TYPE_NEW_POST = 'new_post'
WS_NOTIFICATION_TYPE = 'notification_type'
WS_CHANNEL_THREAD = "thread:"
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()
neko259
Implemented ini settings parser
r1153 max_thread_count = settings.get_int('Messages', 'MaxThreadCount')
if thread_count > max_thread_count:
num_threads_to_delete = thread_count - max_thread_count
neko259
Code cleanup. Update only edited fields while performing thread archiving or post editing. Remove image when post is removed
r715 old_threads = threads[thread_count - num_threads_to_delete:]
for thread in old_threads:
neko259
Implemented ini settings parser
r1153 if settings.get_bool('Storage', 'ArchiveThreads'):
neko259
Moved imageboard settings to the boards settings module. Added setting to disable archive
r716 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
neko259
Added 'bumpable' field. Disable thread bump once and for all, not counting it...
r863 thread.bumpable = False
neko259
Moved imageboard settings to the boards settings module. Added setting to disable archive
r716 thread.last_edit_time = timezone.now()
neko259
Update all posts in thread diff when the thread become not bumpable (BB-66)
r1029 thread.update_posts_time()
neko259
Added 'bumpable' field. Disable thread bump once and for all, not counting it...
r863 thread.save(update_fields=['archived', 'last_edit_time', 'bumpable'])
neko259
Moved imageboard settings to the boards settings module. Added setting to disable archive
r716
neko259
Faster way of obtaining new post count
r1345 def get_new_posts(self, datas):
query = None
# TODO Use classes instead of dicts
for data in datas:
neko259
Fixed last post link in new favorite posts api
r1346 if data['last_id'] != FAV_THREAD_NO_UPDATES:
q = (Q(id=data['op'].get_thread().id)
& Q(multi_replies__id__gt=data['last_id']))
if query is None:
query = q
else:
query = query | q
if query is not None:
return self.filter(query).annotate(
new_post_count=Count('multi_replies'))
neko259
Faster way of obtaining new post count
r1345
def get_new_post_count(self, datas):
neko259
Fixed reflink migration. Fixed new_post API when there are not favorite...
r1347 new_posts = self.get_new_posts(datas)
return new_posts.aggregate(total_count=Count('multi_replies'))\
['total_count'] if new_posts else 0
neko259
Faster way of obtaining new post count
r1345
neko259
Code cleanup. Update only edited fields while performing thread archiving or post editing. Remove image when post is removed
r715
neko259
Fixed thread max posts to not create new migration each time it changes in settings
r1136 def get_thread_max_posts():
neko259
Implemented ini settings parser
r1153 return settings.get_int('Messages', 'MaxPostsPerThread')
neko259
Fixed thread max posts to not create new migration each time it changes in settings
r1136
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'
neko259
Show related tags in the tag page
r1269 tags = models.ManyToManyField('Tag', related_name='thread_tags')
neko259
Added index to thread bump time as sorts on it happen often
r966 bump_time = models.DateTimeField(db_index=True)
neko259
Moved thread model to a separate module
r691 last_edit_time = models.DateTimeField()
archived = models.BooleanField(default=False)
neko259
Added 'bumpable' field. Disable thread bump once and for all, not counting it...
r863 bumpable = models.BooleanField(default=True)
neko259
Fixed thread max posts to not create new migration each time it changes in settings
r1136 max_posts = models.IntegerField(default=get_thread_max_posts)
neko259
Moved thread model to a separate module
r691
neko259
Refactored type hints for thread model
r1186 def get_tags(self) -> QuerySet:
neko259
Moved thread model to a separate module
r691 """
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():
neko259
Update all posts in thread diff when the thread become not bumpable (BB-66)
r1029 self.bump_time = self.last_edit_time
neko259
Moved thread model to a separate module
r691
neko259
If we are replying a multi-thread post, update all its threads and their...
r1046 self.update_bump_status()
neko259
Bump thread only after adding post to it
r885
neko259
Moved thread model to a separate module
r691 logger.info('Bumped thread %d' % self.id)
neko259
Added type hints to some models and managers
r1083 def has_post_limit(self) -> bool:
neko259
Added ability to disable bump limit of a thread
r1055 return self.max_posts > 0
neko259
Fixed moving thread to bump limit. Fixed multipost in the not bumpable thread
r1134 def update_bump_status(self, exclude_posts=None):
neko259
Added ability to disable bump limit of a thread
r1055 if self.has_post_limit() and self.get_reply_count() >= self.max_posts:
neko259
If we are replying a multi-thread post, update all its threads and their...
r1046 self.bumpable = False
neko259
Fixed moving thread to bump limit. Fixed multipost in the not bumpable thread
r1134 self.update_posts_time(exclude_posts=exclude_posts)
neko259
If we are replying a multi-thread post, update all its threads and their...
r1046
neko259
Added ability to cache method result with additional arguments. Cache thread...
r1106 def _get_cache_key(self):
return [datetime_to_epoch(self.last_edit_time)]
@cached_result(key_method=_get_cache_key)
neko259
Added type hints to some models and managers
r1083 def get_reply_count(self) -> int:
neko259
Removed unecessary connection of a thread to its replies, cause posts are...
r958 return self.get_replies().count()
neko259
Moved thread model to a separate module
r691
neko259
Added ability to cache method result with additional arguments. Cache thread...
r1106 @cached_result(key_method=_get_cache_key)
neko259
Added type hints to some models and managers
r1083 def get_images_count(self) -> int:
neko259
Removed unecessary connection of a thread to its replies, cause posts are...
r958 return self.get_replies().annotate(images_count=Count(
neko259
Refactored post and thread models
r1091 'images')).aggregate(Sum('images_count'))['images_count__sum']
neko259
Moved thread model to a separate module
r691
neko259
Added type hints to some models and managers
r1083 def can_bump(self) -> bool:
neko259
Moved thread model to a separate module
r691 """
Checks if the thread can be bumped by replying to it.
"""
neko259
Don't check new posts in the archived threads
r1344 return self.bumpable and not self.is_archived()
neko259
Moved thread model to a separate module
r691
neko259
Refactored type hints for thread model
r1186 def get_last_replies(self) -> QuerySet:
neko259
Moved thread model to a separate module
r691 """
Gets several last replies, not including opening post
"""
neko259
Implemented ini settings parser
r1153 last_replies_count = settings.get_int('View', 'LastRepliesCount')
if last_replies_count > 0:
neko259
Moved thread model to a separate module
r691 reply_count = self.get_reply_count()
if reply_count > 0:
neko259
Implemented ini settings parser
r1153 reply_count_to_show = min(last_replies_count,
neko259
Moved thread model to a separate module
r691 reply_count - 1)
neko259
Optimized loading post images in post template
r694 replies = self.get_replies()
neko259
Backed out changeset 68e7bfc6c078
r987 last_replies = replies[reply_count - reply_count_to_show:]
neko259
Moved thread model to a separate module
r691
return last_replies
neko259
Added type hints to some models and managers
r1083 def get_skipped_replies_count(self) -> int:
neko259
Moved thread model to a separate module
r691 """
Gets number of posts between opening post and last replies.
"""
reply_count = self.get_reply_count()
neko259
Implemented ini settings parser
r1153 last_replies_count = min(settings.get_int('View', 'LastRepliesCount'),
neko259
Moved thread model to a separate module
r691 reply_count - 1)
return reply_count - last_replies_count - 1
neko259
Refactored type hints for thread model
r1186 def get_replies(self, view_fields_only=False) -> QuerySet:
neko259
Moved thread model to a separate module
r691 """
Gets sorted thread posts
"""
neko259
Faster way of obtaining new post count
r1345 query = self.multi_replies.order_by('pub_time').prefetch_related(
neko259
Save "opening post" flag with the post itself and don't count it every time. Speed up getting posts with attachments and images
r1337 'images', 'thread', 'threads', 'attachments')
neko259
Moved thread model to a separate module
r691 if view_fields_only:
neko259
Fixed issue with deferring a field no more exists
r1079 query = query.defer('poster_ip')
neko259
Moved thread model to a separate module
r691 return query.all()
neko259
Refactored type hints for thread model
r1186 def get_top_level_replies(self) -> QuerySet:
neko259
Added tree mode for the thread
r1180 return self.get_replies().exclude(refposts__threads__in=[self])
neko259
Refactored type hints for thread model
r1186 def get_replies_with_images(self, view_fields_only=False) -> QuerySet:
neko259
Delete replies properly when deleting a thread. Delete thread directly, not by...
r950 """
Gets replies that have at least one image attached
"""
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 return self.get_replies(view_fields_only).annotate(images_count=Count(
'images')).filter(images_count__gt=0)
neko259
Added type hints to some models and managers
r1083 def get_opening_post(self, only_id=False) -> Post:
neko259
Moved thread model to a separate module
r691 """
Gets the first post of the thread
"""
neko259
Removed unecessary connection of a thread to its replies, cause posts are...
r958 query = self.get_replies().order_by('pub_time')
neko259
Backed out changeset a37f5ca1da43
r949 if only_id:
query = query.only('id')
opening_post = query.first()
return opening_post
neko259
Moved thread model to a separate module
r691
neko259
Added ability to cache method result with additional arguments. Cache thread...
r1106 @cached_result()
neko259
Added type hints to some models and managers
r1083 def get_opening_post_id(self) -> int:
neko259
Moved thread model to a separate module
r691 """
Gets ID of the first thread post.
"""
neko259
Started work on the method caching decorator (BB-57)
r957 return self.get_opening_post(only_id=True).id
neko259
Moved thread model to a separate module
r691
def get_pub_time(self):
"""
Gets opening post's pub time because thread does not have its own one.
"""
neko259
Backed out changeset a37f5ca1da43
r949 return self.get_opening_post().pub_time
neko259
Use own search form and view
r718
neko259
Show thread, post and tag names in admin with python3
r875 def __str__(self):
neko259
Delete replies properly when deleting a thread. Delete thread directly, not by...
r950 return 'T#{}/{}'.format(self.id, self.get_opening_post_id())
neko259
Refactoring
r1027
neko259
Added type hints to some models and managers
r1083 def get_tag_url_list(self) -> list:
neko259
Update all posts in thread diff when the thread become not bumpable (BB-66)
r1029 return boards.models.Tag.objects.get_tag_url_list(self.get_tags())
neko259
Fixed moving thread to bump limit. Fixed multipost in the not bumpable thread
r1134 def update_posts_time(self, exclude_posts=None):
neko259
Fixed thread bumping
r1221 last_edit_time = self.last_edit_time
neko259
Fixed reflink migration. Fixed new_post API when there are not favorite...
r1347 for post in self.multi_replies.all():
neko259
Fixed updating thread posts when reaching bumplimit. Updated logo
r1219 if exclude_posts is None or post not in exclude_posts:
neko259
Fixed moving thread to bump limit. Fixed multipost in the not bumpable thread
r1134 # Manual update is required because uids are generated on save
neko259
Fixed thread bumping
r1221 post.last_edit_time = last_edit_time
neko259
Fixed moving thread to bump limit. Fixed multipost in the not bumpable thread
r1134 post.save(update_fields=['last_edit_time'])
neko259
Added index on post. Update post uids when the thread reaches bumplimit
r1120
neko259
Fixed thread bumping
r1221 post.get_threads().update(last_edit_time=last_edit_time)
neko259
Refactored websockets notifications and updating threads when updating posts
r1088
neko259
Refactored post and thread models
r1091 def notify_clients(self):
neko259
Implemented ini settings parser
r1153 if not settings.get_bool('External', 'WebsocketsEnabled'):
neko259
Refactored websockets notifications and updating threads when updating posts
r1088 return
client = Client()
channel_name = WS_CHANNEL_THREAD + str(self.get_opening_post_id())
client.publish(channel_name, {
WS_NOTIFICATION_TYPE: WS_NOTIFICATION_TYPE_NEW_POST,
})
neko259
Added ability to cache method result with additional arguments. Cache thread...
r1106 client.send()
neko259
Added ability to show multiple banners. Added "view on site" link for the post...
r1149
def get_absolute_url(self):
return self.get_opening_post().get_absolute_url()
neko259
Show only sections in the image tags list in random images
r1257
def get_required_tags(self):
return self.get_tags().filter(required=True)
neko259
Favorite threads with new posts counter
r1323
def get_replies_newer(self, post_id):
return self.get_replies().filter(id__gt=post_id)
neko259
Don't check new posts in the archived threads
r1344 def is_archived(self):
return self.archived