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