##// END OF EJS Templates
Converting file name to a preudo-unique number instead of the original name.
neko259 -
r50:9ceb712a default
parent child Browse files
Show More
@@ -1,241 +1,248 b''
1 1 import os
2 from random import random
2 3 import re
3 4 from django.db import models
4 5 from django.utils import timezone
5 6 import time
6 7 import math
7 8
8 9 from neboard import settings
9 10 from markupfield.fields import MarkupField
10 11
11 12 import thumbs
12 13
13 14 NO_PARENT = -1
14 15 NO_IP = '0.0.0.0'
15 16 UNKNOWN_UA = ''
16 17
17 18
18 def update_image_filename(instance, filename):
19 """Get unique image filename"""
20
21 path = 'images/'
22 new_name = str(int(time.mktime(time.gmtime()))) + '_' + filename
23 return os.path.join(path, new_name)
24
25
26 19 class PostManager(models.Manager):
27 20 ALL_PAGES = -1
28 21
29 22 def create_post(self, title, text, image=None, parent_id=NO_PARENT,
30 23 ip=NO_IP, tags=None):
31 24 post = self.create(title=title,
32 25 text=text,
33 26 pub_time=timezone.now(),
34 27 parent=parent_id,
35 28 image=image,
36 29 poster_ip=ip,
37 30 poster_user_agent=UNKNOWN_UA,
38 31 last_edit_time=timezone.now())
39 32
40 33 if tags:
41 34 for tag in tags:
42 35 post.tags.add(tag)
43 36
44 37 if parent_id != NO_PARENT:
45 38 self._bump_thread(parent_id)
46 39 else:
47 40 self._delete_old_threads()
48 41
49 42 return post
50 43
51 44 def delete_post(self, post):
52 45 children = self.filter(parent=post.id)
53 46 for child in children:
54 47 self.delete_post(child)
55 48 post.delete()
56 49
57 50 def delete_posts_by_ip(self, ip):
58 51 posts = self.filter(poster_ip=ip)
59 52 for post in posts:
60 53 self.delete_post(post)
61 54
62 55 def get_threads(self, tag=None, page=ALL_PAGES):
63 56 if tag:
64 57 threads = self.filter(parent=NO_PARENT, tags=tag)
65 58 else:
66 59 threads = self.filter(parent=NO_PARENT)
67 60 threads = list(threads.order_by('-last_edit_time'))
68 61
69 62 if page != self.ALL_PAGES:
70 63 thread_count = len(threads)
71 64
72 65 if page < self.get_thread_page_count(tag=tag):
73 66 start_thread = page * settings.THREADS_PER_PAGE
74 67 end_thread = min(start_thread + settings.THREADS_PER_PAGE,
75 68 thread_count)
76 69 threads = threads[start_thread:end_thread]
77 70
78 71 return threads
79 72
80 73 def get_thread(self, opening_post_id):
81 74 opening_post = self.get(id=opening_post_id)
82 75
83 76 if opening_post.parent == NO_PARENT:
84 77 replies = self.filter(parent=opening_post_id)
85 78
86 79 thread = [opening_post]
87 80 thread.extend(replies)
88 81
89 82 return thread
90 83
91 84 def exists(self, post_id):
92 85 posts = self.filter(id=post_id)
93 86
94 87 return len(posts) > 0
95 88
96 89 def get_thread_page_count(self, tag=None):
97 90 if tag:
98 91 threads = self.filter(parent=NO_PARENT, tags=tag)
99 92 else:
100 93 threads = self.filter(parent=NO_PARENT)
101 94
102 95 return int(math.ceil(len(threads) / float(settings.THREADS_PER_PAGE)))
103 96
104 97
105 98 def _delete_old_threads(self):
106 99 """
107 100 Preserves maximum thread count. If there are too many threads,
108 101 delete the old ones.
109 102 """
110 103
111 104 # TODO Try to find a better way to get the active thread count.
112 105
113 106 # TODO Move old threads to the archive instead of deleting them.
114 107 # Maybe make some 'old' field in the model to indicate the thread
115 108 # must not be shown and be able for replying.
116 109
117 110 threads = self.get_threads()
118 111 thread_count = len(threads)
119 112
120 113 if thread_count > settings.MAX_THREAD_COUNT:
121 114 num_threads_to_delete = thread_count - settings.MAX_THREAD_COUNT
122 115 old_threads = threads[-num_threads_to_delete:]
123 116
124 117 for thread in old_threads:
125 118 self.delete_post(thread)
126 119
127 120 def _bump_thread(self, thread_id):
128 121 thread = self.get(id=thread_id)
129 122
130 123 if thread.can_bump():
131 124 thread.last_edit_time = timezone.now()
132 125 thread.save()
133 126
134 127
135 128 class TagManager(models.Manager):
136 129 def get_not_empty_tags(self):
137 130 all_tags = self.all().order_by('name')
138 131 tags = []
139 132 for tag in all_tags:
140 133 if not tag.is_empty():
141 134 tags.append(tag)
142 135
143 136 return tags
144 137
145 138
146 139 class Tag(models.Model):
147 140 """
148 141 A tag is a text node assigned to the post. The tag serves as a board
149 142 section. There can be multiple tags for each message
150 143 """
151 144
152 145 objects = TagManager()
153 146
154 147 name = models.CharField(max_length=100)
155 148 # TODO Connect the tag to its posts to check the number of threads for
156 149 # the tag.
157 150
158 151 def __unicode__(self):
159 152 return self.name
160 153
161 154 def is_empty(self):
162 155 return self.get_post_count() == 0
163 156
164 157 def get_post_count(self):
165 158 posts_with_tag = Post.objects.get_threads(tag=self)
166 159 return len(posts_with_tag)
167 160
168 161
169 162 class Post(models.Model):
170 163 """A post is a message."""
171 164
165 IMAGES_DIRECTORY = 'images/'
166 FILE_EXTENSION_DELIMITER = '.'
167
172 168 objects = PostManager()
173 169
170 def _update_image_filename(self, filename):
171 """Get unique image filename"""
172
173 path = self.IMAGES_DIRECTORY
174 new_name = str(int(time.mktime(time.gmtime())))
175 new_name += str(int(random() * 1000))
176 new_name += self.FILE_EXTENSION_DELIMITER
177 new_name += filename.split(self.FILE_EXTENSION_DELIMITER)[-1:][0]
178
179 return os.path.join(path, new_name)
180
174 181 title = models.CharField(max_length=50)
175 182 pub_time = models.DateTimeField()
176 183 text = MarkupField(default_markup_type='markdown', escape_html=True)
177 image = thumbs.ImageWithThumbsField(upload_to=update_image_filename,
184 image = thumbs.ImageWithThumbsField(upload_to=_update_image_filename,
178 185 blank=True, sizes=((200, 150),))
179 186 poster_ip = models.IPAddressField()
180 187 poster_user_agent = models.TextField()
181 188 parent = models.BigIntegerField()
182 189 tags = models.ManyToManyField(Tag)
183 190 last_edit_time = models.DateTimeField()
184 191
185 192 regex_pretty = re.compile(r'^\d(0)+$')
186 193 regex_same = re.compile(r'^(.)\1+$')
187 194
188 195 def __unicode__(self):
189 196 return self.title + ' (' + self.text.raw + ')'
190 197
191 198 def _get_replies(self):
192 199 return Post.objects.filter(parent=self.id)
193 200
194 201 def get_reply_count(self):
195 202 return len(self._get_replies())
196 203
197 204 def get_images_count(self):
198 205 images_count = 1 if self.image else 0
199 206 for reply in self._get_replies():
200 207 if reply.image:
201 208 images_count += 1
202 209
203 210 return images_count
204 211
205 212 def get_gets_count(self):
206 213 gets_count = 1 if self.is_get() else 0
207 214 for reply in self._get_replies():
208 215 if reply.is_get():
209 216 gets_count += 1
210 217
211 218 return gets_count
212 219
213 220 def is_get(self):
214 221 """If the post has pretty id (1, 1000, 77777), than it is called GET"""
215 222
216 223 first = self.id == 1
217 224
218 225 id_str = str(self.id)
219 226 pretty = self.regex_pretty.match(id_str)
220 227 same_digits = self.regex_same.match(id_str)
221 228
222 229 return first or pretty or same_digits
223 230
224 231 def can_bump(self):
225 232 """Check if the thread can be bumped by replying"""
226 233
227 234 replies_count = len(Post.objects.get_thread(self.id))
228 235
229 236 return replies_count <= settings.MAX_POSTS_PER_THREAD
230 237
231 238
232 239 class Admin(models.Model):
233 240 """
234 241 Model for admin users
235 242 """
236 243 name = models.CharField(max_length=100)
237 244 password = models.CharField(max_length=100)
238 245
239 246 def __unicode__(self):
240 247 return self.name + '/' + '*' * len(self.password)
241 248
General Comments 0
You need to be logged in to leave comments. Login now