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