##// END OF EJS Templates
Fixed some translation issues. Changed default captcha setting to "off" to pass tests. Removed the maximum page scale. This refs #36 and fixes #26, #2
neko259 -
r85:895eadaa default
parent child Browse files
Show More
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
@@ -1,141 +1,141 b''
1 # SOME DESCRIPTIVE TITLE.
1 # SOME DESCRIPTIVE TITLE.
2 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
2 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3 # This file is distributed under the same license as the PACKAGE package.
3 # This file is distributed under the same license as the PACKAGE package.
4 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
4 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
5 #
5 #
6 msgid ""
6 msgid ""
7 msgstr ""
7 msgstr ""
8 "Project-Id-Version: PACKAGE VERSION\n"
8 "Project-Id-Version: PACKAGE VERSION\n"
9 "Report-Msgid-Bugs-To: \n"
9 "Report-Msgid-Bugs-To: \n"
10 "POT-Creation-Date: 2013-06-09 17:35+0300\n"
10 "POT-Creation-Date: 2013-06-10 22:27+0300\n"
11 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
11 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
12 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13 "Language-Team: LANGUAGE <LL@li.org>\n"
13 "Language-Team: LANGUAGE <LL@li.org>\n"
14 "Language: ru\n"
14 "Language: ru\n"
15 "MIME-Version: 1.0\n"
15 "MIME-Version: 1.0\n"
16 "Content-Type: text/plain; charset=UTF-8\n"
16 "Content-Type: text/plain; charset=UTF-8\n"
17 "Content-Transfer-Encoding: 8bit\n"
17 "Content-Transfer-Encoding: 8bit\n"
18 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
18 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
19 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
19 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
20
20
21 #: templates/base.html:27
21 #: templates/boards/base.html:27
22 msgid "All threads"
22 msgid "All threads"
23 msgstr "Все темы"
23 msgstr "Все темы"
24
24
25 #: templates/base.html:33
25 #: templates/boards/base.html:33
26 msgid "Settings"
26 msgid "Settings"
27 msgstr "Настройки"
27 msgstr "Настройки"
28
28
29 #: templates/base.html:40
29 #: templates/boards/base.html:40
30 msgid "Up"
30 msgid "Up"
31 msgstr "Вверх"
31 msgstr "Вверх"
32
32
33 #: templates/posting_general.html:18
33 #: templates/boards/posting_general.html:18
34 msgid "Tag: "
34 msgid "Tag: "
35 msgstr "Тег: "
35 msgstr "Тег: "
36
36
37 #: templates/posting_general.html:35 templates/posting_general.html.py:79
37 #: templates/boards/posting_general.html:35
38 #: templates/thread.html:27
38 #: templates/boards/posting_general.html:79 templates/boards/thread.html:27
39 #, fuzzy
39 #, fuzzy
40 msgid "Post image"
40 msgid "Post image"
41 msgstr "Изображение сообщения"
41 msgstr "Изображение сообщения"
42
42
43 #: templates/posting_general.html:46
43 #: templates/boards/posting_general.html:46
44 msgid "Reply"
44 msgid "Reply"
45 msgstr "Ответ"
45 msgstr "Ответ"
46
46
47 #: templates/posting_general.html:53 templates/thread.html:107
47 #: templates/boards/posting_general.html:53 templates/boards/thread.html:107
48 msgid "replies"
48 msgid "replies"
49 msgstr "ответов"
49 msgstr "ответов"
50
50
51 #: templates/posting_general.html:54 templates/thread.html:108
51 #: templates/boards/posting_general.html:54 templates/boards/thread.html:108
52 msgid "images"
52 msgid "images"
53 msgstr "изображений"
53 msgstr "изображений"
54
54
55 #: templates/posting_general.html:56 templates/posting_general.html.py:127
55 #: templates/boards/posting_general.html:56
56 #: templates/thread.html:49
56 #: templates/boards/posting_general.html:127 templates/boards/thread.html:49
57 msgid "Tags"
57 msgid "Tags"
58 msgstr "Теги"
58 msgstr "Теги"
59
59
60 #: templates/posting_general.html:109
60 #: templates/boards/posting_general.html:109
61 msgid "Create new thread"
61 msgid "Create new thread"
62 msgstr "Создать новую тему"
62 msgstr "Создать новую тему"
63
63
64 #: templates/posting_general.html:112 templates/thread.html:71
64 #: templates/boards/posting_general.html:112 templates/boards/thread.html:71
65 msgid "Title"
65 msgid "Title"
66 msgstr "Заголовок"
66 msgstr "Заголовок"
67
67
68 #: templates/posting_general.html:117 templates/thread.html:76
68 #: templates/boards/posting_general.html:117 templates/boards/thread.html:76
69 msgid "Text"
69 msgid "Text"
70 msgstr "Текст"
70 msgstr "Текст"
71
71
72 #: templates/posting_general.html:122 templates/thread.html:81
72 #: templates/boards/posting_general.html:122 templates/boards/thread.html:81
73 msgid "Image"
73 msgid "Image"
74 msgstr "Изображение"
74 msgstr "Изображение"
75
75
76 #: templates/posting_general.html:136 templates/thread.html:91
76 #: templates/boards/posting_general.html:136 templates/boards/thread.html:91
77 msgid "Post"
77 msgid "Post"
78 msgstr "Отправить"
78 msgstr "Отправить"
79
79
80 #: templates/posting_general.html:152
80 #: templates/boards/posting_general.html:138
81 #, fuzzy
81 msgid "Tags must be delimited by spaces. Text or image is required."
82 msgstr ""
83 "Теги должны быть разделены пробелами. Текст или изображение обязательны."
84
85 #: templates/boards/posting_general.html:141 templates/boards/thread.html:93
86 msgid "Basic markdown syntax."
87 msgstr "Базовый синтаксис markdown."
88
89 #: templates/boards/posting_general.html:152
82 msgid "Pages:"
90 msgid "Pages:"
83 msgstr "Страницы: "
91 msgstr "Страницы: "
84
92
85 #: templates/settings.html:13
93 #: templates/boards/settings.html:13
86 msgid "Theme"
94 msgid "Theme"
87 msgstr "Тема"
95 msgstr "Тема"
88
96
89 #: templates/settings.html:29
97 #: templates/boards/settings.html:29
90 msgid "Save"
98 msgid "Save"
91 msgstr "Сохранить"
99 msgstr "Сохранить"
92
100
93 #: templates/tags.html:7
101 #: templates/boards/tags.html:7
94 msgid "tags"
102 msgid "tags"
95 msgstr "тегов"
103 msgstr "тегов"
96
104
97 #: templates/thread.html:39
105 #: templates/boards/thread.html:39
98 msgid "Get!"
106 msgid "Get!"
99 msgstr "Гет!"
107 msgstr "Гет!"
100
108
101 #: templates/thread.html:68
109 #: templates/boards/thread.html:68
102 msgid "Reply to thread"
110 msgid "Reply to thread"
103 msgstr "Ответить в тему"
111 msgstr "Ответить в тему"
104
112
105 #: templates/thread.html:93
113 #: templates/boards/thread.html:94
106 msgid "Basic markdown syntax."
107 msgstr "Базовый синтаксис markdown."
108
109 #: templates/thread.html:94
110 msgid "Example: "
114 msgid "Example: "
111 msgstr "Пример: "
115 msgstr "Пример: "
112
116
113 #: templates/thread.html:94
117 #: templates/boards/thread.html:94
114 msgid "italic"
118 msgid "italic"
115 msgstr "курсив"
119 msgstr "курсив"
116
120
117 #: templates/thread.html:95
121 #: templates/boards/thread.html:95
118 msgid "bold"
122 msgid "bold"
119 msgstr "полужирный"
123 msgstr "полужирный"
120
124
121 #: templates/thread.html:96
125 #: templates/boards/thread.html:96
122 msgid "Quotes can be inserted with"
126 msgid "Quotes can be inserted with"
123 msgstr "Цитаты могут быть вставлены при помощи"
127 msgstr "Цитаты могут быть вставлены при помощи"
124
128
125 #: templates/thread.html:97
129 #: templates/boards/thread.html:97
126 msgid "Links to answers can be inserted with"
130 msgid "Links to answers can be inserted with"
127 msgstr "Ссылки на ответы могут быть вставлены с помощью"
131 msgstr "Ссылки на ответы могут быть вставлены с помощью"
128
132
129 #: templates/thread.html:109
133 #: templates/boards/thread.html:109
130 msgid "Last update: "
134 msgid "Last update: "
131 msgstr "Последнее обновление: "
135 msgstr "Последнее обновление: "
132
136
133 #~ msgid "View"
137 #~ msgid "View"
134 #~ msgstr "Просмотр"
138 #~ msgstr "Просмотр"
135
139
136 #~ msgid "gets"
140 #~ msgid "gets"
137 #~ msgstr "гетов"
141 #~ msgstr "гетов"
138
139 #~ msgid "Tags must be delimited by spaces. Text or image is required."
140 #~ msgstr ""
141 #~ "Теги должны быть разделены пробелами. Текст или изображение обязательны."
@@ -1,288 +1,288 b''
1 import os
1 import os
2 from random import random
2 from random import random
3 import re
3 import re
4 import time
4 import time
5 import math
5 import math
6
6
7 from django.db import models
7 from django.db import models
8 from django.http import Http404
8 from django.http import Http404
9 from django.utils import timezone
9 from django.utils import timezone
10 from markupfield.fields import MarkupField
10 from markupfield.fields import MarkupField
11
11
12 from neboard import settings
12 from neboard import settings
13 import thumbs
13 import thumbs
14
14
15 IMAGE_THUMB_SIZE = (200, 150)
15 IMAGE_THUMB_SIZE = (200, 150)
16
16
17 TITLE_MAX_LENGTH = 50
17 TITLE_MAX_LENGTH = 50
18
18
19 DEFAULT_MARKUP_TYPE = 'markdown'
19 DEFAULT_MARKUP_TYPE = 'markdown'
20
20
21 NO_PARENT = -1
21 NO_PARENT = -1
22 NO_IP = '0.0.0.0'
22 NO_IP = '0.0.0.0'
23 UNKNOWN_UA = ''
23 UNKNOWN_UA = ''
24 ALL_PAGES = -1
24 ALL_PAGES = -1
25 OPENING_POST_WEIGHT = 5
25 OPENING_POST_POPULARITY_WEIGHT = 2
26 IMAGES_DIRECTORY = 'images/'
26 IMAGES_DIRECTORY = 'images/'
27 FILE_EXTENSION_DELIMITER = '.'
27 FILE_EXTENSION_DELIMITER = '.'
28
28
29 REGEX_PRETTY = re.compile(r'^\d(0)+$')
29 REGEX_PRETTY = re.compile(r'^\d(0)+$')
30 REGEX_SAME = re.compile(r'^(.)\1+$')
30 REGEX_SAME = re.compile(r'^(.)\1+$')
31
31
32
32
33 class PostManager(models.Manager):
33 class PostManager(models.Manager):
34 def create_post(self, title, text, image=None, parent_id=NO_PARENT,
34 def create_post(self, title, text, image=None, parent_id=NO_PARENT,
35 ip=NO_IP, tags=None):
35 ip=NO_IP, tags=None):
36 post = self.create(title=title,
36 post = self.create(title=title,
37 text=text,
37 text=text,
38 pub_time=timezone.now(),
38 pub_time=timezone.now(),
39 parent=parent_id,
39 parent=parent_id,
40 image=image,
40 image=image,
41 poster_ip=ip,
41 poster_ip=ip,
42 poster_user_agent=UNKNOWN_UA,
42 poster_user_agent=UNKNOWN_UA,
43 last_edit_time=timezone.now())
43 last_edit_time=timezone.now())
44
44
45 if tags:
45 if tags:
46 map(post.tags.add, tags)
46 map(post.tags.add, tags)
47
47
48 if parent_id != NO_PARENT:
48 if parent_id != NO_PARENT:
49 self._bump_thread(parent_id)
49 self._bump_thread(parent_id)
50 else:
50 else:
51 self._delete_old_threads()
51 self._delete_old_threads()
52
52
53 return post
53 return post
54
54
55 def delete_post(self, post):
55 def delete_post(self, post):
56 children = self.filter(parent=post.id)
56 children = self.filter(parent=post.id)
57 for child in children:
57 for child in children:
58 self.delete_post(child)
58 self.delete_post(child)
59 post.delete()
59 post.delete()
60
60
61 def delete_posts_by_ip(self, ip):
61 def delete_posts_by_ip(self, ip):
62 posts = self.filter(poster_ip=ip)
62 posts = self.filter(poster_ip=ip)
63 for post in posts:
63 for post in posts:
64 self.delete_post(post)
64 self.delete_post(post)
65
65
66 def get_threads(self, tag=None, page=ALL_PAGES):
66 def get_threads(self, tag=None, page=ALL_PAGES):
67 if tag:
67 if tag:
68 threads = self.filter(parent=NO_PARENT, tags=tag)
68 threads = self.filter(parent=NO_PARENT, tags=tag)
69 else:
69 else:
70 threads = self.filter(parent=NO_PARENT)
70 threads = self.filter(parent=NO_PARENT)
71
71
72 if not threads:
72 if not threads:
73 raise Http404
73 raise Http404
74
74
75 threads = threads.order_by('-last_edit_time')
75 threads = threads.order_by('-last_edit_time')
76
76
77 if page != ALL_PAGES:
77 if page != ALL_PAGES:
78 thread_count = len(threads)
78 thread_count = len(threads)
79
79
80 if page < self.get_thread_page_count(tag=tag):
80 if page < self.get_thread_page_count(tag=tag):
81 start_thread = page * settings.THREADS_PER_PAGE
81 start_thread = page * settings.THREADS_PER_PAGE
82 end_thread = min(start_thread + settings.THREADS_PER_PAGE,
82 end_thread = min(start_thread + settings.THREADS_PER_PAGE,
83 thread_count)
83 thread_count)
84 threads = threads[start_thread:end_thread]
84 threads = threads[start_thread:end_thread]
85
85
86 return threads
86 return threads
87
87
88 def get_thread(self, opening_post_id):
88 def get_thread(self, opening_post_id):
89 try:
89 try:
90 opening_post = self.get(id=opening_post_id)
90 opening_post = self.get(id=opening_post_id)
91 except Post.DoesNotExist:
91 except Post.DoesNotExist:
92 raise Http404
92 raise Http404
93
93
94 if opening_post.parent == NO_PARENT:
94 if opening_post.parent == NO_PARENT:
95 replies = self.filter(parent=opening_post_id)
95 replies = self.filter(parent=opening_post_id)
96
96
97 thread = [opening_post]
97 thread = [opening_post]
98 thread.extend(replies)
98 thread.extend(replies)
99
99
100 return thread
100 return thread
101
101
102 def exists(self, post_id):
102 def exists(self, post_id):
103 posts = self.filter(id=post_id)
103 posts = self.filter(id=post_id)
104
104
105 return posts.count() > 0
105 return posts.count() > 0
106
106
107 def get_thread_page_count(self, tag=None):
107 def get_thread_page_count(self, tag=None):
108 if tag:
108 if tag:
109 threads = self.filter(parent=NO_PARENT, tags=tag)
109 threads = self.filter(parent=NO_PARENT, tags=tag)
110 else:
110 else:
111 threads = self.filter(parent=NO_PARENT)
111 threads = self.filter(parent=NO_PARENT)
112
112
113 return int(math.ceil(threads.count() / float(
113 return int(math.ceil(threads.count() / float(
114 settings.THREADS_PER_PAGE)))
114 settings.THREADS_PER_PAGE)))
115
115
116 def _delete_old_threads(self):
116 def _delete_old_threads(self):
117 """
117 """
118 Preserves maximum thread count. If there are too many threads,
118 Preserves maximum thread count. If there are too many threads,
119 delete the old ones.
119 delete the old ones.
120 """
120 """
121
121
122 # TODO Move old threads to the archive instead of deleting them.
122 # TODO Move old threads to the archive instead of deleting them.
123 # Maybe make some 'old' field in the model to indicate the thread
123 # Maybe make some 'old' field in the model to indicate the thread
124 # must not be shown and be able for replying.
124 # must not be shown and be able for replying.
125
125
126 threads = self.get_threads()
126 threads = self.get_threads()
127 thread_count = len(threads)
127 thread_count = len(threads)
128
128
129 if thread_count > settings.MAX_THREAD_COUNT:
129 if thread_count > settings.MAX_THREAD_COUNT:
130 num_threads_to_delete = thread_count - settings.MAX_THREAD_COUNT
130 num_threads_to_delete = thread_count - settings.MAX_THREAD_COUNT
131 old_threads = threads[thread_count - num_threads_to_delete:]
131 old_threads = threads[thread_count - num_threads_to_delete:]
132
132
133 for thread in old_threads:
133 for thread in old_threads:
134 self.delete_post(thread)
134 self.delete_post(thread)
135
135
136 def _bump_thread(self, thread_id):
136 def _bump_thread(self, thread_id):
137 thread = self.get(id=thread_id)
137 thread = self.get(id=thread_id)
138
138
139 if thread.can_bump():
139 if thread.can_bump():
140 thread.last_edit_time = timezone.now()
140 thread.last_edit_time = timezone.now()
141 thread.save()
141 thread.save()
142
142
143
143
144 class TagManager(models.Manager):
144 class TagManager(models.Manager):
145 def get_not_empty_tags(self):
145 def get_not_empty_tags(self):
146 all_tags = self.all().order_by('name')
146 all_tags = self.all().order_by('name')
147 tags = []
147 tags = []
148 for tag in all_tags:
148 for tag in all_tags:
149 if not tag.is_empty():
149 if not tag.is_empty():
150 tags.append(tag)
150 tags.append(tag)
151
151
152 return tags
152 return tags
153
153
154 def get_popular_tags(self):
154 def get_popular_tags(self):
155 all_tags = self.get_not_empty_tags()
155 all_tags = self.get_not_empty_tags()
156
156
157 sorted_tags = sorted(all_tags, key=lambda tag: tag.get_popularity(),
157 sorted_tags = sorted(all_tags, key=lambda tag: tag.get_popularity(),
158 reverse=True)
158 reverse=True)
159
159
160 return sorted_tags[:settings.POPULAR_TAGS]
160 return sorted_tags[:settings.POPULAR_TAGS]
161
161
162
162
163 class Tag(models.Model):
163 class Tag(models.Model):
164 """
164 """
165 A tag is a text node assigned to the post. The tag serves as a board
165 A tag is a text node assigned to the post. The tag serves as a board
166 section. There can be multiple tags for each message
166 section. There can be multiple tags for each message
167 """
167 """
168
168
169 objects = TagManager()
169 objects = TagManager()
170
170
171 name = models.CharField(max_length=100)
171 name = models.CharField(max_length=100)
172 # TODO Connect the tag to its posts to check the number of threads for
172 # TODO Connect the tag to its posts to check the number of threads for
173 # the tag.
173 # the tag.
174
174
175 def __unicode__(self):
175 def __unicode__(self):
176 return self.name
176 return self.name
177
177
178 def is_empty(self):
178 def is_empty(self):
179 return self.get_post_count() == 0
179 return self.get_post_count() == 0
180
180
181 def get_post_count(self):
181 def get_post_count(self):
182 posts_with_tag = Post.objects.get_threads(tag=self)
182 posts_with_tag = Post.objects.get_threads(tag=self)
183 return posts_with_tag.count()
183 return posts_with_tag.count()
184
184
185 def get_popularity(self):
185 def get_popularity(self):
186 posts_with_tag = Post.objects.get_threads(tag=self)
186 posts_with_tag = Post.objects.get_threads(tag=self)
187 reply_count = 0
187 reply_count = 0
188 for post in posts_with_tag:
188 for post in posts_with_tag:
189 reply_count += post.get_reply_count()
189 reply_count += post.get_reply_count()
190 reply_count += OPENING_POST_WEIGHT
190 reply_count += OPENING_POST_POPULARITY_WEIGHT
191
191
192 return reply_count
192 return reply_count
193
193
194
194
195 class Post(models.Model):
195 class Post(models.Model):
196 """A post is a message."""
196 """A post is a message."""
197
197
198 objects = PostManager()
198 objects = PostManager()
199
199
200 def _update_image_filename(self, filename):
200 def _update_image_filename(self, filename):
201 """Get unique image filename"""
201 """Get unique image filename"""
202
202
203 path = IMAGES_DIRECTORY
203 path = IMAGES_DIRECTORY
204 new_name = str(int(time.mktime(time.gmtime())))
204 new_name = str(int(time.mktime(time.gmtime())))
205 new_name += str(int(random() * 1000))
205 new_name += str(int(random() * 1000))
206 new_name += FILE_EXTENSION_DELIMITER
206 new_name += FILE_EXTENSION_DELIMITER
207 new_name += filename.split(FILE_EXTENSION_DELIMITER)[-1:][0]
207 new_name += filename.split(FILE_EXTENSION_DELIMITER)[-1:][0]
208
208
209 return os.path.join(path, new_name)
209 return os.path.join(path, new_name)
210
210
211 title = models.CharField(max_length=TITLE_MAX_LENGTH)
211 title = models.CharField(max_length=TITLE_MAX_LENGTH)
212 pub_time = models.DateTimeField()
212 pub_time = models.DateTimeField()
213 text = MarkupField(default_markup_type=DEFAULT_MARKUP_TYPE,
213 text = MarkupField(default_markup_type=DEFAULT_MARKUP_TYPE,
214 escape_html=True)
214 escape_html=True)
215 image = thumbs.ImageWithThumbsField(upload_to=_update_image_filename,
215 image = thumbs.ImageWithThumbsField(upload_to=_update_image_filename,
216 blank=True, sizes=(IMAGE_THUMB_SIZE,))
216 blank=True, sizes=(IMAGE_THUMB_SIZE,))
217 poster_ip = models.IPAddressField()
217 poster_ip = models.IPAddressField()
218 poster_user_agent = models.TextField()
218 poster_user_agent = models.TextField()
219 parent = models.BigIntegerField()
219 parent = models.BigIntegerField()
220 tags = models.ManyToManyField(Tag)
220 tags = models.ManyToManyField(Tag)
221 last_edit_time = models.DateTimeField()
221 last_edit_time = models.DateTimeField()
222
222
223 def __unicode__(self):
223 def __unicode__(self):
224 return '#' + str(self.id) + ' ' + self.title + ' (' + self.text.raw + \
224 return '#' + str(self.id) + ' ' + self.title + ' (' + self.text.raw + \
225 ')'
225 ')'
226
226
227 def _get_replies(self):
227 def _get_replies(self):
228 return Post.objects.filter(parent=self.id)
228 return Post.objects.filter(parent=self.id)
229
229
230 def get_reply_count(self):
230 def get_reply_count(self):
231 return self._get_replies().count()
231 return self._get_replies().count()
232
232
233 def get_images_count(self):
233 def get_images_count(self):
234 images_count = 1 if self.image else 0
234 images_count = 1 if self.image else 0
235 for reply in self._get_replies():
235 for reply in self._get_replies():
236 if reply.image:
236 if reply.image:
237 images_count += 1
237 images_count += 1
238
238
239 return images_count
239 return images_count
240
240
241 def get_gets_count(self):
241 def get_gets_count(self):
242 gets_count = 1 if self.is_get() else 0
242 gets_count = 1 if self.is_get() else 0
243 for reply in self._get_replies():
243 for reply in self._get_replies():
244 if reply.is_get():
244 if reply.is_get():
245 gets_count += 1
245 gets_count += 1
246
246
247 return gets_count
247 return gets_count
248
248
249 def is_get(self):
249 def is_get(self):
250 """If the post has pretty id (1, 1000, 77777), than it is called GET"""
250 """If the post has pretty id (1, 1000, 77777), than it is called GET"""
251
251
252 first = self.id == 1
252 first = self.id == 1
253
253
254 id_str = str(self.id)
254 id_str = str(self.id)
255 pretty = REGEX_PRETTY.match(id_str)
255 pretty = REGEX_PRETTY.match(id_str)
256 same_digits = REGEX_SAME.match(id_str)
256 same_digits = REGEX_SAME.match(id_str)
257
257
258 return first or pretty or same_digits
258 return first or pretty or same_digits
259
259
260 def can_bump(self):
260 def can_bump(self):
261 """Check if the thread can be bumped by replying"""
261 """Check if the thread can be bumped by replying"""
262
262
263 replies_count = len(Post.objects.get_thread(self.id))
263 replies_count = len(Post.objects.get_thread(self.id))
264
264
265 return replies_count <= settings.MAX_POSTS_PER_THREAD
265 return replies_count <= settings.MAX_POSTS_PER_THREAD
266
266
267 def get_last_replies(self):
267 def get_last_replies(self):
268 if settings.LAST_REPLIES_COUNT > 0:
268 if settings.LAST_REPLIES_COUNT > 0:
269 reply_count = self.get_reply_count()
269 reply_count = self.get_reply_count()
270
270
271 if reply_count > 0:
271 if reply_count > 0:
272 reply_count_to_show = min(settings.LAST_REPLIES_COUNT,
272 reply_count_to_show = min(settings.LAST_REPLIES_COUNT,
273 reply_count)
273 reply_count)
274 last_replies = self._get_replies()[reply_count
274 last_replies = self._get_replies()[reply_count
275 - reply_count_to_show:]
275 - reply_count_to_show:]
276
276
277 return last_replies
277 return last_replies
278
278
279
279
280 class Admin(models.Model):
280 class Admin(models.Model):
281 """
281 """
282 Model for admin users
282 Model for admin users
283 """
283 """
284 name = models.CharField(max_length=100)
284 name = models.CharField(max_length=100)
285 password = models.CharField(max_length=100)
285 password = models.CharField(max_length=100)
286
286
287 def __unicode__(self):
287 def __unicode__(self):
288 return self.name + '/' + '*' * len(self.password)
288 return self.name + '/' + '*' * len(self.password)
@@ -1,44 +1,44 b''
1 {% load staticfiles %}
1 {% load staticfiles %}
2 {% load i18n %}
2 {% load i18n %}
3
3
4 <!DOCTYPE html>
4 <!DOCTYPE html>
5 <html>
5 <html>
6 <head>
6 <head>
7 <link rel="stylesheet" type="text/css"
7 <link rel="stylesheet" type="text/css"
8 href="{{ STATIC_URL }}css/jquery.fancybox.css" media="all"/>
8 href="{{ STATIC_URL }}css/jquery.fancybox.css" media="all"/>
9 <link rel="stylesheet" type="text/css"
9 <link rel="stylesheet" type="text/css"
10 href="{{ STATIC_URL }}css/{{ theme }}/base_page.css" media="all"/>
10 href="{{ STATIC_URL }}css/{{ theme }}/base_page.css" media="all"/>
11 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
11 <meta name="viewport" content="width=device-width, initial-scale=1"/>
12 {% block head %}{% endblock %}
12 {% block head %}{% endblock %}
13 </head>
13 </head>
14 <body>
14 <body>
15 <script src="{{ STATIC_URL }}js/jquery-2.0.1.min.js"></script>
15 <script src="{{ STATIC_URL }}js/jquery-2.0.1.min.js"></script>
16 <script src="{{ STATIC_URL }}js/jquery.fancybox.pack.js"></script>
16 <script src="{{ STATIC_URL }}js/jquery.fancybox.pack.js"></script>
17 <script src="{{ STATIC_URL }}js/main.js"></script>
17 <script src="{{ STATIC_URL }}js/main.js"></script>
18 <div id="admin_panel">
18 <div id="admin_panel">
19
19
20 {% if request.session.admin == True %}
20 {% if request.session.admin == True %}
21 Admin panel TODO: Need to implement <BR />
21 Admin panel TODO: Need to implement <BR />
22 {% endif %}
22 {% endif %}
23
23
24 </div>
24 </div>
25
25
26 <div class="navigation_panel">
26 <div class="navigation_panel">
27 <a class="link" href="{% url 'index' %}">{% trans "All threads" %}</a>
27 <a class="link" href="{% url 'index' %}">{% trans "All threads" %}</a>
28 {% for tag in tags %}
28 {% for tag in tags %}
29 <a class="tag" href=" {% url 'tag' tag_name=tag.name %}">
29 <a class="tag" href=" {% url 'tag' tag_name=tag.name %}">
30 {{ tag.name }}</a>({{ tag.get_post_count }})
30 {{ tag.name }}</a>({{ tag.get_post_count }})
31 {% endfor %}
31 {% endfor %}
32 <a class="tag" href="{% url 'tags' %}">[...]</a>
32 <a class="tag" href="{% url 'tags' %}">[...]</a>
33 <a class="link" href="{% url 'settings' %}">{% trans 'Settings' %}</a>
33 <a class="link" href="{% url 'settings' %}">{% trans 'Settings' %}</a>
34 </div>
34 </div>
35
35
36 {% block content %}{% endblock %}
36 {% block content %}{% endblock %}
37
37
38 <div class="navigation_panel">
38 <div class="navigation_panel">
39 {% block metapanel %}{% endblock %}
39 {% block metapanel %}{% endblock %}
40 <a class="link" href="#top">{% trans 'Up' %}</a>
40 <a class="link" href="#top">{% trans 'Up' %}</a>
41 </div>
41 </div>
42
42
43 </body>
43 </body>
44 </html> No newline at end of file
44 </html>
@@ -1,164 +1,164 b''
1 {% extends "boards/base.html" %}
1 {% extends "boards/base.html" %}
2
2
3 {% load i18n %}
3 {% load i18n %}
4 {% load markup %}
4 {% load markup %}
5
5
6 {% block head %}
6 {% block head %}
7 {% if tag %}
7 {% if tag %}
8 <title>Neboard - {{ tag }}</title>
8 <title>Neboard - {{ tag }}</title>
9 {% else %}
9 {% else %}
10 <title>Neboard</title>
10 <title>Neboard</title>
11 {% endif %}
11 {% endif %}
12 {% endblock %}
12 {% endblock %}
13
13
14 {% block content %}
14 {% block content %}
15
15
16 {% if tag %}
16 {% if tag %}
17 <div class="tag_info">
17 <div class="tag_info">
18 <h2>{% trans 'Tag: ' %}{{ tag }}</h2>
18 <h2>{% trans 'Tag: ' %}{{ tag }}</h2>
19 </div>
19 </div>
20 {% endif %}
20 {% endif %}
21
21
22 {% if threads %}
22 {% if threads %}
23 {% for thread in threads %}
23 {% for thread in threads %}
24 <div class="thread">
24 <div class="thread">
25 {% if thread.can_bump %}
25 {% if thread.can_bump %}
26 <div class="post">
26 <div class="post">
27 {% else %}
27 {% else %}
28 <div class="post dead_post">
28 <div class="post dead_post">
29 {% endif %}
29 {% endif %}
30 {% if thread.image %}
30 {% if thread.image %}
31 <div class="image">
31 <div class="image">
32 <a class="fancy"
32 <a class="fancy"
33 href="{{ thread.image.url }}"><img
33 href="{{ thread.image.url }}"><img
34 src="{{ thread.image.url_200x150 }}"
34 src="{{ thread.image.url_200x150 }}"
35 alt="{% trans 'Post image' %}" />
35 alt="{% trans 'Post image' %}" />
36 </a>
36 </a>
37 </div>
37 </div>
38 {% endif %}
38 {% endif %}
39 <div class="message">
39 <div class="message">
40 <div class="post-info">
40 <div class="post-info">
41 <span class="title">{{ thread.title }}</span>
41 <span class="title">{{ thread.title }}</span>
42 <a class="post_id" href="{% url 'thread' thread.id %}">
42 <a class="post_id" href="{% url 'thread' thread.id %}">
43 (#{{ thread.id }})</a>
43 (#{{ thread.id }})</a>
44 [{{ thread.pub_time }}]
44 [{{ thread.pub_time }}]
45 [<a class="link" href="{% url 'thread' thread.id %}#form"
45 [<a class="link" href="{% url 'thread' thread.id %}#form"
46 >{% trans "Reply" %}</a>]
46 >{% trans "Reply" %}</a>]
47 </div>
47 </div>
48 {% autoescape off %}
48 {% autoescape off %}
49 {{ thread.text.rendered|truncatewords_html:50 }}
49 {{ thread.text.rendered|truncatewords_html:50 }}
50 {% endautoescape %}
50 {% endautoescape %}
51 </div>
51 </div>
52 <div class="metadata">
52 <div class="metadata">
53 {{ thread.get_reply_count }} {% trans 'replies' %},
53 {{ thread.get_reply_count }} {% trans 'replies' %},
54 {{ thread.get_images_count }} {% trans 'images' %}.
54 {{ thread.get_images_count }} {% trans 'images' %}.
55 {% if thread.tags.all %}
55 {% if thread.tags.all %}
56 <span class="tags">{% trans 'Tags' %}:
56 <span class="tags">{% trans 'Tags' %}:
57 {% for tag in thread.tags.all %}
57 {% for tag in thread.tags.all %}
58 <a class="tag" href="
58 <a class="tag" href="
59 {% url 'tag' tag_name=tag.name %}">
59 {% url 'tag' tag_name=tag.name %}">
60 {{ tag.name }}</a>
60 {{ tag.name }}</a>
61 {% endfor %}
61 {% endfor %}
62 </span>
62 </span>
63 {% endif %}
63 {% endif %}
64 </div>
64 </div>
65 </div>
65 </div>
66 {% if thread.get_last_replies %}
66 {% if thread.get_last_replies %}
67 <div class="last-replies">
67 <div class="last-replies">
68 {% for post in thread.get_last_replies %}
68 {% for post in thread.get_last_replies %}
69 {% if thread.can_bump %}
69 {% if thread.can_bump %}
70 <div class="post">
70 <div class="post">
71 {% else %}
71 {% else %}
72 <div class="post dead_post">
72 <div class="post dead_post">
73 {% endif %}
73 {% endif %}
74 {% if post.image %}
74 {% if post.image %}
75 <div class="image">
75 <div class="image">
76 <a class="fancy"
76 <a class="fancy"
77 href="{{ post.image.url }}"><img
77 href="{{ post.image.url }}"><img
78 src=" {{ post.image.url_200x150 }}"
78 src=" {{ post.image.url_200x150 }}"
79 alt="{% trans 'Post image' %}" />
79 alt="{% trans 'Post image' %}" />
80 </a>
80 </a>
81 </div>
81 </div>
82 {% endif %}
82 {% endif %}
83 <div class="message">
83 <div class="message">
84 <div class="post-info">
84 <div class="post-info">
85 <span class="title">{{ post.title }}</span>
85 <span class="title">{{ post.title }}</span>
86 <a class="post_id" href="
86 <a class="post_id" href="
87 {% url 'thread' thread.id %}#{{ post.id }}">
87 {% url 'thread' thread.id %}#{{ post.id }}">
88 (#{{ post.id }})</a>
88 (#{{ post.id }})</a>
89 [{{ post.pub_time }}]
89 [{{ post.pub_time }}]
90 </div>
90 </div>
91 {% autoescape off %}
91 {% autoescape off %}
92 {{ post.text.rendered|truncatewords_html:50 }}
92 {{ post.text.rendered|truncatewords_html:50 }}
93 {% endautoescape %}
93 {% endautoescape %}
94 </div>
94 </div>
95 </div>
95 </div>
96 {% endfor %}
96 {% endfor %}
97 </div>
97 </div>
98 {% endif %}
98 {% endif %}
99 </div>
99 </div>
100 {% endfor %}
100 {% endfor %}
101 {% else %}
101 {% else %}
102 No threads found.
102 No threads found.
103 <hr />
103 <hr />
104 {% endif %}
104 {% endif %}
105
105
106 <form enctype="multipart/form-data" method="post">{% csrf_token %}
106 <form enctype="multipart/form-data" method="post">{% csrf_token %}
107 <div class="post-form-w">
107 <div class="post-form-w">
108
108
109 <div class="form-title">{% trans "Create new thread" %}</div>
109 <div class="form-title">{% trans "Create new thread" %}</div>
110 <div class="post-form">
110 <div class="post-form">
111 <div class="form-row">
111 <div class="form-row">
112 <div class="form-label">{% trans 'Title' %}</div>
112 <div class="form-label">{% trans 'Title' %}</div>
113 <div class="form-input">{{ form.title }}</div>
113 <div class="form-input">{{ form.title }}</div>
114 <div class="form-errors">{{ form.title.errors }}</div>
114 <div class="form-errors">{{ form.title.errors }}</div>
115 </div>
115 </div>
116 <div class="form-row">
116 <div class="form-row">
117 <div class="form-label">{% trans 'Text' %}</div>
117 <div class="form-label">{% trans 'Text' %}</div>
118 <div class="form-input">{{ form.text }}</div>
118 <div class="form-input">{{ form.text }}</div>
119 <div class="form-errors">{{ form.text.errors }}</div>
119 <div class="form-errors">{{ form.text.errors }}</div>
120 </div>
120 </div>
121 <div class="form-row">
121 <div class="form-row">
122 <div class="form-label">{% trans 'Image' %}</div>
122 <div class="form-label">{% trans 'Image' %}</div>
123 <div class="form-input">{{ form.image }}</div>
123 <div class="form-input">{{ form.image }}</div>
124 <div class="form-errors">{{ form.image.errors }}</div>
124 <div class="form-errors">{{ form.image.errors }}</div>
125 </div>
125 </div>
126 <div class="form-row">
126 <div class="form-row">
127 <div class="form-label">{% trans 'Tags' %}</div>
127 <div class="form-label">{% trans 'Tags' %}</div>
128 <div class="form-input">{{ form.tags }}</div>
128 <div class="form-input">{{ form.tags }}</div>
129 <div class="form-errors">{{ form.tags.errors }}</div>
129 <div class="form-errors">{{ form.tags.errors }}</div>
130 </div>
130 </div>
131 <div class="form-row">
131 <div class="form-row">
132 {{ form.captcha }}
132 {{ form.captcha }}
133 </div>
133 </div>
134 </div>
134 </div>
135 <div class="form-submit">
135 <div class="form-submit">
136 <input type="submit" value="{% trans "Post" %}"/></div>
136 <input type="submit" value="{% trans "Post" %}"/></div>
137 <div>Tags must be delimited by spaces. Text or image is required
137 <div>
138 </div>
138 {% trans 'Tags must be delimited by spaces. Text or image is required.' %}
139 <div>Use <a
139 </div>
140 href="http://daringfireball.net/projects/markdown/basics">
140 <div><a href="http://daringfireball.net/projects/markdown/basics">
141 markdown</a> syntax for posting.</div>
141 {% trans 'Basic markdown syntax.' %}</a></div>
142 </div>
142 </div>
143 </form>
143 </form>
144
144
145 {% endblock %}
145 {% endblock %}
146
146
147 {% block metapanel %}
147 {% block metapanel %}
148
148
149 <span class="metapanel">
149 <span class="metapanel">
150 <b><a href="https://bitbucket.org/neko259/neboard/">Neboard</a>
150 <b><a href="https://bitbucket.org/neko259/neboard/">Neboard</a>
151 2013-05 (dev)</b>
151 pre1.0</b>
152 {% trans "Pages:" %}
152 {% trans "Pages:" %}
153 {% for page in pages %}
153 {% for page in pages %}
154 [<a href="
154 [<a href="
155 {% if tag %}
155 {% if tag %}
156 {% url "tag" tag_name=tag page=page %}
156 {% url "tag" tag_name=tag page=page %}
157 {% else %}
157 {% else %}
158 {% url "index" page=page %}
158 {% url "index" page=page %}
159 {% endif %}
159 {% endif %}
160 ">{{ page }}</a>]
160 ">{{ page }}</a>]
161 {% endfor %}
161 {% endfor %}
162 </span>
162 </span>
163
163
164 {% endblock %}
164 {% endblock %}
@@ -1,195 +1,195 b''
1 # Django settings for neboard project.
1 # Django settings for neboard project.
2 import os
2 import os
3 import markdown
3 import markdown
4 from boards.mdx_neboard import markdown_extended
4 from boards.mdx_neboard import markdown_extended
5
5
6 DEBUG = True
6 DEBUG = True
7 TEMPLATE_DEBUG = DEBUG
7 TEMPLATE_DEBUG = DEBUG
8
8
9 ADMINS = (
9 ADMINS = (
10 # ('Your Name', 'your_email@example.com'),
10 # ('Your Name', 'your_email@example.com'),
11 ('admin', 'admin@example.com')
11 ('admin', 'admin@example.com')
12 )
12 )
13
13
14 MANAGERS = ADMINS
14 MANAGERS = ADMINS
15
15
16 DATABASES = {
16 DATABASES = {
17 'default': {
17 'default': {
18 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
18 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
19 'NAME': 'database.db', # Or path to database file if using sqlite3.
19 'NAME': 'database.db', # Or path to database file if using sqlite3.
20 'USER': '', # Not used with sqlite3.
20 'USER': '', # Not used with sqlite3.
21 'PASSWORD': '', # Not used with sqlite3.
21 'PASSWORD': '', # Not used with sqlite3.
22 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
22 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
23 'PORT': '', # Set to empty string for default. Not used with sqlite3.
23 'PORT': '', # Set to empty string for default. Not used with sqlite3.
24 }
24 }
25 }
25 }
26
26
27 # Local time zone for this installation. Choices can be found here:
27 # Local time zone for this installation. Choices can be found here:
28 # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
28 # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
29 # although not all choices may be available on all operating systems.
29 # although not all choices may be available on all operating systems.
30 # In a Windows environment this must be set to your system time zone.
30 # In a Windows environment this must be set to your system time zone.
31 TIME_ZONE = 'Europe/Kiev'
31 TIME_ZONE = 'Europe/Kiev'
32
32
33 # Language code for this installation. All choices can be found here:
33 # Language code for this installation. All choices can be found here:
34 # http://www.i18nguy.com/unicode/language-identifiers.html
34 # http://www.i18nguy.com/unicode/language-identifiers.html
35 LANGUAGE_CODE = 'ru-RU'
35 LANGUAGE_CODE = 'ru-RU'
36
36
37 SITE_ID = 1
37 SITE_ID = 1
38
38
39 # If you set this to False, Django will make some optimizations so as not
39 # If you set this to False, Django will make some optimizations so as not
40 # to load the internationalization machinery.
40 # to load the internationalization machinery.
41 USE_I18N = True
41 USE_I18N = True
42
42
43 # If you set this to False, Django will not format dates, numbers and
43 # If you set this to False, Django will not format dates, numbers and
44 # calendars according to the current locale.
44 # calendars according to the current locale.
45 USE_L10N = True
45 USE_L10N = True
46
46
47 # If you set this to False, Django will not use timezone-aware datetimes.
47 # If you set this to False, Django will not use timezone-aware datetimes.
48 USE_TZ = True
48 USE_TZ = True
49
49
50 # Absolute filesystem path to the directory that will hold user-uploaded files.
50 # Absolute filesystem path to the directory that will hold user-uploaded files.
51 # Example: "/home/media/media.lawrence.com/media/"
51 # Example: "/home/media/media.lawrence.com/media/"
52 MEDIA_ROOT = './media/'
52 MEDIA_ROOT = './media/'
53
53
54 # URL that handles the media served from MEDIA_ROOT. Make sure to use a
54 # URL that handles the media served from MEDIA_ROOT. Make sure to use a
55 # trailing slash.
55 # trailing slash.
56 # Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
56 # Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
57 MEDIA_URL = '/media/'
57 MEDIA_URL = '/media/'
58
58
59 # Absolute path to the directory static files should be collected to.
59 # Absolute path to the directory static files should be collected to.
60 # Don't put anything in this directory yourself; store your static files
60 # Don't put anything in this directory yourself; store your static files
61 # in apps' "static/" subdirectories and in STATICFILES_DIRS.
61 # in apps' "static/" subdirectories and in STATICFILES_DIRS.
62 # Example: "/home/media/media.lawrence.com/static/"
62 # Example: "/home/media/media.lawrence.com/static/"
63 STATIC_ROOT = ''
63 STATIC_ROOT = ''
64
64
65 # URL prefix for static files.
65 # URL prefix for static files.
66 # Example: "http://media.lawrence.com/static/"
66 # Example: "http://media.lawrence.com/static/"
67 STATIC_URL = '/static/'
67 STATIC_URL = '/static/'
68
68
69 # Additional locations of static files
69 # Additional locations of static files
70 # It is really a hack, put real paths, not related
70 # It is really a hack, put real paths, not related
71 STATICFILES_DIRS = (
71 STATICFILES_DIRS = (
72 os.path.dirname(__file__) + '/boards/static',
72 os.path.dirname(__file__) + '/boards/static',
73
73
74 # '/d/work/python/django/neboard/neboard/boards/static',
74 # '/d/work/python/django/neboard/neboard/boards/static',
75 # Put strings here, like "/home/html/static" or "C:/www/django/static".
75 # Put strings here, like "/home/html/static" or "C:/www/django/static".
76 # Always use forward slashes, even on Windows.
76 # Always use forward slashes, even on Windows.
77 # Don't forget to use absolute paths, not relative paths.
77 # Don't forget to use absolute paths, not relative paths.
78 )
78 )
79
79
80 # List of finder classes that know how to find static files in
80 # List of finder classes that know how to find static files in
81 # various locations.
81 # various locations.
82 STATICFILES_FINDERS = (
82 STATICFILES_FINDERS = (
83 'django.contrib.staticfiles.finders.FileSystemFinder',
83 'django.contrib.staticfiles.finders.FileSystemFinder',
84 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
84 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
85 # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
85 # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
86 )
86 )
87
87
88 # Make this unique, and don't share it with anybody.
88 # Make this unique, and don't share it with anybody.
89 SECRET_KEY = '@1rc$o(7=tt#kd+4s$u6wchm**z^)4x90)7f6z(i&amp;55@o11*8o'
89 SECRET_KEY = '@1rc$o(7=tt#kd+4s$u6wchm**z^)4x90)7f6z(i&amp;55@o11*8o'
90
90
91 # List of callables that know how to import templates from various sources.
91 # List of callables that know how to import templates from various sources.
92 TEMPLATE_LOADERS = (
92 TEMPLATE_LOADERS = (
93 'django.template.loaders.filesystem.Loader',
93 'django.template.loaders.filesystem.Loader',
94 'django.template.loaders.app_directories.Loader',
94 'django.template.loaders.app_directories.Loader',
95 # 'django.template.loaders.eggs.Loader',
95 # 'django.template.loaders.eggs.Loader',
96 )
96 )
97
97
98 TEMPLATE_CONTEXT_PROCESSORS = (
98 TEMPLATE_CONTEXT_PROCESSORS = (
99 'django.core.context_processors.media',
99 'django.core.context_processors.media',
100 'django.core.context_processors.static',
100 'django.core.context_processors.static',
101 'django.core.context_processors.request',
101 'django.core.context_processors.request',
102 'django.contrib.auth.context_processors.auth',
102 'django.contrib.auth.context_processors.auth',
103 )
103 )
104
104
105 MIDDLEWARE_CLASSES = (
105 MIDDLEWARE_CLASSES = (
106 'django.middleware.common.CommonMiddleware',
106 'django.middleware.common.CommonMiddleware',
107 'django.contrib.sessions.middleware.SessionMiddleware',
107 'django.contrib.sessions.middleware.SessionMiddleware',
108 # 'django.middleware.csrf.CsrfViewMiddleware',
108 # 'django.middleware.csrf.CsrfViewMiddleware',
109 'django.contrib.auth.middleware.AuthenticationMiddleware',
109 'django.contrib.auth.middleware.AuthenticationMiddleware',
110 'django.contrib.messages.middleware.MessageMiddleware',
110 'django.contrib.messages.middleware.MessageMiddleware',
111 # Uncomment the next line for simple clickjacking protection:
111 # Uncomment the next line for simple clickjacking protection:
112 # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
112 # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
113 )
113 )
114
114
115 ROOT_URLCONF = 'neboard.urls'
115 ROOT_URLCONF = 'neboard.urls'
116
116
117 # Python dotted path to the WSGI application used by Django's runserver.
117 # Python dotted path to the WSGI application used by Django's runserver.
118 WSGI_APPLICATION = 'neboard.wsgi.application'
118 WSGI_APPLICATION = 'neboard.wsgi.application'
119
119
120 TEMPLATE_DIRS = (
120 TEMPLATE_DIRS = (
121 # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
121 # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
122 # Always use forward slashes, even on Windows.
122 # Always use forward slashes, even on Windows.
123 # Don't forget to use absolute paths, not relative paths.
123 # Don't forget to use absolute paths, not relative paths.
124 'templates',
124 'templates',
125 )
125 )
126
126
127 INSTALLED_APPS = (
127 INSTALLED_APPS = (
128 'django.contrib.auth',
128 'django.contrib.auth',
129 'django.contrib.contenttypes',
129 'django.contrib.contenttypes',
130 'django.contrib.sessions',
130 'django.contrib.sessions',
131 'django.contrib.sites',
131 'django.contrib.sites',
132 'django.contrib.messages',
132 'django.contrib.messages',
133 'django.contrib.staticfiles',
133 'django.contrib.staticfiles',
134 # Uncomment the next line to enable the admin:
134 # Uncomment the next line to enable the admin:
135 'django.contrib.admin',
135 'django.contrib.admin',
136 # Uncomment the next line to enable admin documentation:
136 # Uncomment the next line to enable admin documentation:
137 # 'django.contrib.admindocs',
137 # 'django.contrib.admindocs',
138 'django.contrib.markup',
138 'django.contrib.markup',
139 'django_cleanup',
139 'django_cleanup',
140 'boards',
140 'boards',
141 'captcha',
141 'captcha',
142 )
142 )
143
143
144 # TODO: NEED DESIGN FIXES
144 # TODO: NEED DESIGN FIXES
145 CAPTCHA_OUTPUT_FORMAT = (u' %(hidden_field)s '
145 CAPTCHA_OUTPUT_FORMAT = (u' %(hidden_field)s '
146 u'<div class="form-label">%(image)s</div>'
146 u'<div class="form-label">%(image)s</div>'
147 u'<div class="form-text">%(text_field)s</div>')
147 u'<div class="form-text">%(text_field)s</div>')
148
148
149 # A sample logging configuration. The only tangible logging
149 # A sample logging configuration. The only tangible logging
150 # performed by this configuration is to send an email to
150 # performed by this configuration is to send an email to
151 # the site admins on every HTTP 500 error when DEBUG=False.
151 # the site admins on every HTTP 500 error when DEBUG=False.
152 # See http://docs.djangoproject.com/en/dev/topics/logging for
152 # See http://docs.djangoproject.com/en/dev/topics/logging for
153 # more details on how to customize your logging configuration.
153 # more details on how to customize your logging configuration.
154 LOGGING = {
154 LOGGING = {
155 'version': 1,
155 'version': 1,
156 'disable_existing_loggers': False,
156 'disable_existing_loggers': False,
157 'filters': {
157 'filters': {
158 'require_debug_false': {
158 'require_debug_false': {
159 '()': 'django.utils.log.RequireDebugFalse'
159 '()': 'django.utils.log.RequireDebugFalse'
160 }
160 }
161 },
161 },
162 'handlers': {
162 'handlers': {
163 'mail_admins': {
163 'mail_admins': {
164 'level': 'ERROR',
164 'level': 'ERROR',
165 'filters': ['require_debug_false'],
165 'filters': ['require_debug_false'],
166 'class': 'django.utils.log.AdminEmailHandler'
166 'class': 'django.utils.log.AdminEmailHandler'
167 }
167 }
168 },
168 },
169 'loggers': {
169 'loggers': {
170 'django.request': {
170 'django.request': {
171 'handlers': ['mail_admins'],
171 'handlers': ['mail_admins'],
172 'level': 'ERROR',
172 'level': 'ERROR',
173 'propagate': True,
173 'propagate': True,
174 },
174 },
175 }
175 }
176 }
176 }
177
177
178 MARKUP_FIELD_TYPES = (
178 MARKUP_FIELD_TYPES = (
179 ('markdown', markdown_extended),
179 ('markdown', markdown_extended),
180 )
180 )
181 # Custom imageboard settings
181 # Custom imageboard settings
182 MAX_POSTS_PER_THREAD = 10 # Thread bumplimit
182 MAX_POSTS_PER_THREAD = 10 # Thread bumplimit
183 MAX_THREAD_COUNT = 500 # Old threads will be deleted to preserve this count
183 MAX_THREAD_COUNT = 500 # Old threads will be deleted to preserve this count
184 THREADS_PER_PAGE = 10
184 THREADS_PER_PAGE = 10
185 SITE_NAME = 'Neboard'
185 SITE_NAME = 'Neboard'
186
186
187 THEMES = [
187 THEMES = [
188 ('md', 'Mystic Dark'),
188 ('md', 'Mystic Dark'),
189 ('sw', 'Snow White') ]
189 ('sw', 'Snow White') ]
190 DEFAULT_THEME = 'md'
190 DEFAULT_THEME = 'md'
191
191
192 POPULAR_TAGS = 10
192 POPULAR_TAGS = 10
193 LAST_REPLIES_COUNT = 3
193 LAST_REPLIES_COUNT = 3
194
194
195 ENABLE_CAPTCHA = True No newline at end of file
195 ENABLE_CAPTCHA = False No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now