##// END OF EJS Templates
Removed thread tag updater
neko259 -
r907:39d20e9b default
parent child Browse files
Show More
@@ -1,191 +1,183 b''
1 import logging
1 import logging
2 from django.db.models import Count, Sum
2 from django.db.models import Count, Sum
3 from django.utils import timezone
3 from django.utils import timezone
4 from django.core.cache import cache
4 from django.core.cache import cache
5 from django.db import models
5 from django.db import models
6 from boards import settings
6 from boards import settings
7
7
8 __author__ = 'neko259'
8 __author__ = 'neko259'
9
9
10
10
11 logger = logging.getLogger(__name__)
11 logger = logging.getLogger(__name__)
12
12
13
13
14 CACHE_KEY_OPENING_POST = 'opening_post_id'
14 CACHE_KEY_OPENING_POST = 'opening_post_id'
15
15
16
16
17 class ThreadManager(models.Manager):
17 class ThreadManager(models.Manager):
18 def process_oldest_threads(self):
18 def process_oldest_threads(self):
19 """
19 """
20 Preserves maximum thread count. If there are too many threads,
20 Preserves maximum thread count. If there are too many threads,
21 archive or delete the old ones.
21 archive or delete the old ones.
22 """
22 """
23
23
24 threads = Thread.objects.filter(archived=False).order_by('-bump_time')
24 threads = Thread.objects.filter(archived=False).order_by('-bump_time')
25 thread_count = threads.count()
25 thread_count = threads.count()
26
26
27 if thread_count > settings.MAX_THREAD_COUNT:
27 if thread_count > settings.MAX_THREAD_COUNT:
28 num_threads_to_delete = thread_count - settings.MAX_THREAD_COUNT
28 num_threads_to_delete = thread_count - settings.MAX_THREAD_COUNT
29 old_threads = threads[thread_count - num_threads_to_delete:]
29 old_threads = threads[thread_count - num_threads_to_delete:]
30
30
31 for thread in old_threads:
31 for thread in old_threads:
32 if settings.ARCHIVE_THREADS:
32 if settings.ARCHIVE_THREADS:
33 self._archive_thread(thread)
33 self._archive_thread(thread)
34 else:
34 else:
35 thread.delete()
35 thread.delete()
36
36
37 logger.info('Processed %d old threads' % num_threads_to_delete)
37 logger.info('Processed %d old threads' % num_threads_to_delete)
38
38
39 def _archive_thread(self, thread):
39 def _archive_thread(self, thread):
40 thread.archived = True
40 thread.archived = True
41 thread.bumpable = False
41 thread.bumpable = False
42 thread.last_edit_time = timezone.now()
42 thread.last_edit_time = timezone.now()
43 thread.save(update_fields=['archived', 'last_edit_time', 'bumpable'])
43 thread.save(update_fields=['archived', 'last_edit_time', 'bumpable'])
44
44
45
45
46 class Thread(models.Model):
46 class Thread(models.Model):
47 objects = ThreadManager()
47 objects = ThreadManager()
48
48
49 class Meta:
49 class Meta:
50 app_label = 'boards'
50 app_label = 'boards'
51
51
52 tags = models.ManyToManyField('Tag')
52 tags = models.ManyToManyField('Tag')
53 bump_time = models.DateTimeField()
53 bump_time = models.DateTimeField()
54 last_edit_time = models.DateTimeField()
54 last_edit_time = models.DateTimeField()
55 replies = models.ManyToManyField('Post', symmetrical=False, null=True,
55 replies = models.ManyToManyField('Post', symmetrical=False, null=True,
56 blank=True, related_name='tre+')
56 blank=True, related_name='tre+')
57 archived = models.BooleanField(default=False)
57 archived = models.BooleanField(default=False)
58 bumpable = models.BooleanField(default=True)
58 bumpable = models.BooleanField(default=True)
59
59
60 def get_tags(self):
60 def get_tags(self):
61 """
61 """
62 Gets a sorted tag list.
62 Gets a sorted tag list.
63 """
63 """
64
64
65 return self.tags.order_by('name')
65 return self.tags.order_by('name')
66
66
67 def bump(self):
67 def bump(self):
68 """
68 """
69 Bumps (moves to up) thread if possible.
69 Bumps (moves to up) thread if possible.
70 """
70 """
71
71
72 if self.can_bump():
72 if self.can_bump():
73 self.bump_time = timezone.now()
73 self.bump_time = timezone.now()
74
74
75 if self.get_reply_count() >= settings.MAX_POSTS_PER_THREAD:
75 if self.get_reply_count() >= settings.MAX_POSTS_PER_THREAD:
76 self.bumpable = False
76 self.bumpable = False
77
77
78 logger.info('Bumped thread %d' % self.id)
78 logger.info('Bumped thread %d' % self.id)
79
79
80 def get_reply_count(self):
80 def get_reply_count(self):
81 return self.replies.count()
81 return self.replies.count()
82
82
83 def get_images_count(self):
83 def get_images_count(self):
84 return self.replies.annotate(images_count=Count(
84 return self.replies.annotate(images_count=Count(
85 'images')).aggregate(Sum('images_count'))['images_count__sum']
85 'images')).aggregate(Sum('images_count'))['images_count__sum']
86
86
87 def can_bump(self):
87 def can_bump(self):
88 """
88 """
89 Checks if the thread can be bumped by replying to it.
89 Checks if the thread can be bumped by replying to it.
90 """
90 """
91
91
92 return self.bumpable
92 return self.bumpable
93
93
94 def get_last_replies(self):
94 def get_last_replies(self):
95 """
95 """
96 Gets several last replies, not including opening post
96 Gets several last replies, not including opening post
97 """
97 """
98
98
99 if settings.LAST_REPLIES_COUNT > 0:
99 if settings.LAST_REPLIES_COUNT > 0:
100 reply_count = self.get_reply_count()
100 reply_count = self.get_reply_count()
101
101
102 if reply_count > 0:
102 if reply_count > 0:
103 reply_count_to_show = min(settings.LAST_REPLIES_COUNT,
103 reply_count_to_show = min(settings.LAST_REPLIES_COUNT,
104 reply_count - 1)
104 reply_count - 1)
105 replies = self.get_replies()
105 replies = self.get_replies()
106 last_replies = replies[reply_count - reply_count_to_show:]
106 last_replies = replies[reply_count - reply_count_to_show:]
107
107
108 return last_replies
108 return last_replies
109
109
110 def get_skipped_replies_count(self):
110 def get_skipped_replies_count(self):
111 """
111 """
112 Gets number of posts between opening post and last replies.
112 Gets number of posts between opening post and last replies.
113 """
113 """
114 reply_count = self.get_reply_count()
114 reply_count = self.get_reply_count()
115 last_replies_count = min(settings.LAST_REPLIES_COUNT,
115 last_replies_count = min(settings.LAST_REPLIES_COUNT,
116 reply_count - 1)
116 reply_count - 1)
117 return reply_count - last_replies_count - 1
117 return reply_count - last_replies_count - 1
118
118
119 def get_replies(self, view_fields_only=False):
119 def get_replies(self, view_fields_only=False):
120 """
120 """
121 Gets sorted thread posts
121 Gets sorted thread posts
122 """
122 """
123
123
124 query = self.replies.order_by('pub_time').prefetch_related('images')
124 query = self.replies.order_by('pub_time').prefetch_related('images')
125 if view_fields_only:
125 if view_fields_only:
126 query = query.defer('poster_user_agent')
126 query = query.defer('poster_user_agent')
127 return query.all()
127 return query.all()
128
128
129 def get_replies_with_images(self, view_fields_only=False):
129 def get_replies_with_images(self, view_fields_only=False):
130 return self.get_replies(view_fields_only).annotate(images_count=Count(
130 return self.get_replies(view_fields_only).annotate(images_count=Count(
131 'images')).filter(images_count__gt=0)
131 'images')).filter(images_count__gt=0)
132
132
133 def add_tag(self, tag):
133 def add_tag(self, tag):
134 """
134 """
135 Connects thread to a tag and tag to a thread
135 Connects thread to a tag and tag to a thread
136 """
136 """
137
137
138 self.tags.add(tag)
138 self.tags.add(tag)
139 tag.threads.add(self)
139 tag.threads.add(self)
140
140
141 def get_opening_post(self, only_id=False):
141 def get_opening_post(self, only_id=False):
142 """
142 """
143 Gets the first post of the thread
143 Gets the first post of the thread
144 """
144 """
145
145
146 query = self.replies.order_by('pub_time')
146 query = self.replies.order_by('pub_time')
147 if only_id:
147 if only_id:
148 query = query.only('id')
148 query = query.only('id')
149 opening_post = query.first()
149 opening_post = query.first()
150
150
151 return opening_post
151 return opening_post
152
152
153 def get_opening_post_id(self):
153 def get_opening_post_id(self):
154 """
154 """
155 Gets ID of the first thread post.
155 Gets ID of the first thread post.
156 """
156 """
157
157
158 cache_key = CACHE_KEY_OPENING_POST + str(self.id)
158 cache_key = CACHE_KEY_OPENING_POST + str(self.id)
159 opening_post_id = cache.get(cache_key)
159 opening_post_id = cache.get(cache_key)
160 if not opening_post_id:
160 if not opening_post_id:
161 opening_post_id = self.get_opening_post(only_id=True).id
161 opening_post_id = self.get_opening_post(only_id=True).id
162 cache.set(cache_key, opening_post_id)
162 cache.set(cache_key, opening_post_id)
163
163
164 return opening_post_id
164 return opening_post_id
165
165
166 def __unicode__(self):
166 def __unicode__(self):
167 return str(self.id)
167 return str(self.id)
168
168
169 def get_pub_time(self):
169 def get_pub_time(self):
170 """
170 """
171 Gets opening post's pub time because thread does not have its own one.
171 Gets opening post's pub time because thread does not have its own one.
172 """
172 """
173
173
174 return self.get_opening_post().pub_time
174 return self.get_opening_post().pub_time
175
175
176 def delete(self, using=None):
176 def delete(self, using=None):
177 if self.replies.exists():
177 if self.replies.exists():
178 self.replies.all().delete()
178 self.replies.all().delete()
179
179
180 super(Thread, self).delete(using)
180 super(Thread, self).delete(using)
181
181
182 def __str__(self):
182 def __str__(self):
183 return 'T#{}/{}'.format(self.id, self.get_opening_post_id())
183 return 'T#{}/{}'.format(self.id, self.get_opening_post_id()) No newline at end of file
184
185 def save(self, force_insert=False, force_update=False, using=None,
186 update_fields=None):
187 super().save(force_insert, force_update, using, update_fields)
188
189 if not update_fields or 'tags' in update_fields:
190 for tag in self.tags.all():
191 tag.threads.add(self) No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now