##// END OF EJS Templates
Compiling regexes for gets. #17 Added pagination. #28 Visually differing the dead (not bumpable) threads.
neko259 -
r46:384df4e1 default
parent child Browse files
Show More
@@ -3,6 +3,7 b' import re'
3 3 from django.db import models
4 4 from django.utils import timezone
5 5 import time
6 import math
6 7
7 8 from neboard import settings
8 9 from markupfield.fields import MarkupField
@@ -23,6 +24,8 b' def update_image_filename(instance, file'
23 24
24 25
25 26 class PostManager(models.Manager):
27 ALL_PAGES = -1
28
26 29 def create_post(self, title, text, image=None, parent_id=NO_PARENT,
27 30 ip=NO_IP, tags=None):
28 31 post = self.create(title=title,
@@ -56,13 +59,22 b' class PostManager(models.Manager):'
56 59 for post in posts:
57 60 self.delete_post(post)
58 61
59 def get_threads(self, tag=None):
62 def get_threads(self, tag=None, page=ALL_PAGES):
60 63 if tag:
61 64 threads = self.filter(parent=NO_PARENT, tags=tag)
62 65 else:
63 66 threads = self.filter(parent=NO_PARENT)
64 67 threads = list(threads.order_by('-last_edit_time'))
65 68
69 if page != self.ALL_PAGES:
70 thread_count = len(threads)
71
72 if page < self.get_thread_page_count(tag=tag):
73 start_thread = page * settings.THREADS_PER_PAGE
74 end_thread = min(start_thread + settings.THREADS_PER_PAGE,
75 thread_count)
76 threads = threads[start_thread:end_thread]
77
66 78 return threads
67 79
68 80 def get_thread(self, opening_post_id):
@@ -81,6 +93,15 b' class PostManager(models.Manager):'
81 93
82 94 return len(posts) > 0
83 95
96 def get_thread_page_count(self, tag=None):
97 if tag:
98 threads = self.filter(parent=NO_PARENT, tags=tag)
99 else:
100 threads = self.filter(parent=NO_PARENT)
101
102 return int(math.ceil(len(threads) / float(settings.THREADS_PER_PAGE)))
103
104
84 105 def _delete_old_threads(self):
85 106 """
86 107 Preserves maximum thread count. If there are too many threads,
@@ -106,8 +127,7 b' class PostManager(models.Manager):'
106 127 def _bump_thread(self, thread_id):
107 128 thread = self.get(id=thread_id)
108 129
109 replies_count = len(self.get_thread(thread_id))
110 if replies_count <= settings.MAX_POSTS_PER_THREAD:
130 if thread.can_bump():
111 131 thread.last_edit_time = timezone.now()
112 132 thread.save()
113 133
@@ -162,6 +182,9 b' class Post(models.Model):'
162 182 tags = models.ManyToManyField(Tag)
163 183 last_edit_time = models.DateTimeField()
164 184
185 regex_pretty = re.compile(r'^\d(0)+$')
186 regex_same = re.compile(r'^(.)\1+$')
187
165 188 def __unicode__(self):
166 189 return self.title + ' (' + self.text.raw + ')'
167 190
@@ -192,12 +215,18 b' class Post(models.Model):'
192 215
193 216 first = self.id == 1
194 217
195 # TODO Compile regexes
218 id_str = str(self.id)
219 pretty = self.regex_pretty.match(id_str)
220 same_digits = self.regex_same.match(id_str)
221
222 return first or pretty or same_digits
196 223
197 id_str = str(self.id)
198 pretty = re.match(r'^\d(0)+$', id_str)
199 same_digits = re.match(r'^(.)\1+$', id_str)
200 return first or pretty or same_digits
224 def can_bump(self):
225 """Check if the thread can be bumped by replying"""
226
227 replies_count = len(Post.objects.get_thread(self.id))
228
229 return replies_count <= settings.MAX_POSTS_PER_THREAD
201 230
202 231
203 232 class Admin(models.Model):
@@ -42,7 +42,7 b' html {'
42 42 color: #fff380;
43 43 }
44 44
45 .post {
45 .post, .dead_post{
46 46 background: #333;
47 47 margin: 5px;
48 48 padding: 10px;
@@ -169,4 +169,8 b' blockquote {'
169 169
170 170 * {
171 171 text-decoration: none;
172 }
173
174 .dead_post {
175 background-color: #442222;
172 176 } No newline at end of file
@@ -107,4 +107,27 b' class BoardTests(TestCase):'
107 107 self._create_post()
108 108
109 109 self.assertEqual(settings.MAX_THREAD_COUNT,
110 len(Post.objects.get_threads())) No newline at end of file
110 len(Post.objects.get_threads()))
111
112 def test_get(self):
113 """Test if the get computes properly"""
114
115 post = self._create_post()
116
117 self.assertTrue(post.is_get())
118
119 def test_pages(self):
120 """Test that the thread list is properly split into pages"""
121
122 PAGE_NUMBER = 2
123
124 for i in range(settings.MAX_THREAD_COUNT):
125 self._create_post()
126
127 all_threads = Post.objects.get_threads()
128
129 posts_in_second_page = Post.objects.get_threads(page=1)
130 first_post = posts_in_second_page[0]
131
132 self.assertEqual(all_threads[settings.THREADS_PER_PAGE].id,
133 first_post.id) No newline at end of file
@@ -4,16 +4,20 b' from boards import views'
4 4 urlpatterns = patterns('',
5 5
6 6 # /boards/
7 url(r'^$', views.index, name = 'index'),
7 url(r'^$', views.index, name='index'),
8 # /boards/page/
9 url(r'^page/(?P<page>\w+)/$', views.index, name='index'),
8 10
9 11 # login page
10 12 url(r'^login$', views.login, name='login'),
11 13 # logout page
12 14 url(r'^logout$', views.logout, name='logout'),
13 15
14 # /boards/tag/
16 # /boards/tag/tag_name/
15 17 url(r'^tag/(?P<tag_name>\w+)/$', views.tag, name='tag'),
16 # /boards/post_id/
18 # /boards/tag/tag_id/page/
19 url(r'^tag/(?P<tag_name>\w+)/page/(?P<page>\w+)/$', views.tag, name='tag'),
20 # /boards/thread/
17 21 url(r'^thread/(?P<post_id>\w+)/$', views.thread, name='thread'),
18 22 # /boards/theme/theme_name/
19 23 url(r'^settings$', views.settings, name='settings'),
@@ -9,18 +9,20 b' from django.http import HttpResponseRedi'
9 9 import neboard
10 10
11 11
12 def index(request):
12 def index(request, page=0):
13 13 context = RequestContext(request)
14 14
15 15 if request.method == 'POST':
16 16 return new_post(request)
17 17 else:
18 threads = Post.objects.get_threads()
18 threads = Post.objects.get_threads(page=int(page))
19 19
20 # TODO Get rid of the duplicate code in index and tag views
20 21 context['threads'] = None if len(threads) == 0 else threads
21 22 context['form'] = forms.ThreadForm()
22 23 context['tags'] = Tag.objects.get_not_empty_tags()
23 24 context['theme'] = _get_theme(request)
25 context['pages'] = range(Post.objects.get_thread_page_count())
24 26
25 27 return render(request, 'posting_general.html',
26 28 context)
@@ -80,11 +82,11 b' def new_post(request, thread_id=boards.m'
80 82 + str(post.id))
81 83
82 84
83 def tag(request, tag_name):
85 def tag(request, tag_name, page=0):
84 86 """Get all tag threads (posts without a parent)."""
85 87
86 88 tag = Tag.objects.get(name=tag_name)
87 threads = Post.objects.get_threads(tag=tag)
89 threads = Post.objects.get_threads(tag=tag, page=int(page))
88 90
89 91 if request.method == 'POST':
90 92 return new_post(request)
@@ -94,6 +96,7 b' def tag(request, tag_name):'
94 96 context['tag'] = tag_name
95 97 context['tags'] = Tag.objects.get_not_empty_tags()
96 98 context['theme'] = _get_theme(request)
99 context['pages'] = range(Post.objects.get_thread_page_count(tag=tag))
97 100
98 101 context['form'] = forms.ThreadForm(initial={'tags': tag_name})
99 102
@@ -168,8 +168,9 b' LOGGING = {'
168 168 }
169 169
170 170 # Custom imageboard settings
171 MAX_POSTS_PER_THREAD = 500 # Thread bumplimit
171 MAX_POSTS_PER_THREAD = 10 # Thread bumplimit
172 172 MAX_THREAD_COUNT = 20 # Old threads will be deleted to preserve this count
173 THREADS_PER_PAGE = 2
173 174 SITE_NAME = 'Neboard'
174 175
175 176 THEMES = [
@@ -11,7 +11,11 b''
11 11
12 12 {% if threads %}
13 13 {% for thread in threads %}
14 <div class="post">
14 {% if thread.can_bump %}
15 <div class="post">
16 {% else %}
17 <div class="dead_post">
18 {% endif %}
15 19 {% if thread.image %}
16 20 <div class="image">
17 21 <a href="{{ thread.image.url }}"><img
@@ -87,7 +91,17 b''
87 91 {% block metapanel %}
88 92
89 93 <span class="metapanel">
90 Neboard 2013-05 (dev)
94 <b>Neboard 2013-05 (dev)</b>
95 {% trans "Pages:" %}
96 {% for page in pages %}
97 [<a href="
98 {% if tag %}
99 {% url "tag" tag_name=tag page=page %}
100 {% else %}
101 {% url "index" page=page %}
102 {% endif %}
103 ">{{ page }}</a>]
104 {% endfor %}
91 105 </span>
92 106
93 107 {% endblock %} No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now