##// END OF EJS Templates
Optimized some post count calls.
neko259 -
r58:e922d63e default
parent child Browse files
Show More
@@ -1,265 +1,267 b''
1 import os
1 import os
2 from random import random
2 from random import random
3 import re
3 import re
4 from django.db import models
4 from django.db import models
5 from django.utils import timezone
5 from django.utils import timezone
6 import time
6 import time
7 import math
7 import math
8 import markdown
8 import markdown
9 from markdown.inlinepatterns import Pattern
9 from markdown.inlinepatterns import Pattern
10 from markdown.util import etree
10 from markdown.util import etree
11
11
12 from neboard import settings
12 from neboard import settings
13 from markupfield.fields import MarkupField
13 from markupfield.fields import MarkupField
14
14
15 import thumbs
15 import thumbs
16
16
17 NO_PARENT = -1
17 NO_PARENT = -1
18 NO_IP = '0.0.0.0'
18 NO_IP = '0.0.0.0'
19 UNKNOWN_UA = ''
19 UNKNOWN_UA = ''
20
20
21
21
22 class PostManager(models.Manager):
22 class PostManager(models.Manager):
23 ALL_PAGES = -1
23 ALL_PAGES = -1
24
24
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 self._bump_thread(parent_id)
41 self._bump_thread(parent_id)
42 else:
42 else:
43 self._delete_old_threads()
43 self._delete_old_threads()
44
44
45 return post
45 return post
46
46
47 def delete_post(self, post):
47 def delete_post(self, post):
48 children = self.filter(parent=post.id)
48 children = self.filter(parent=post.id)
49 for child in children:
49 for child in children:
50 self.delete_post(child)
50 self.delete_post(child)
51 post.delete()
51 post.delete()
52
52
53 def delete_posts_by_ip(self, ip):
53 def delete_posts_by_ip(self, ip):
54 posts = self.filter(poster_ip=ip)
54 posts = self.filter(poster_ip=ip)
55 for post in posts:
55 for post in posts:
56 self.delete_post(post)
56 self.delete_post(post)
57
57
58 def get_threads(self, tag=None, page=ALL_PAGES):
58 def get_threads(self, tag=None, page=ALL_PAGES):
59 if tag:
59 if tag:
60 threads = self.filter(parent=NO_PARENT, tags=tag)
60 threads = self.filter(parent=NO_PARENT, tags=tag)
61 else:
61 else:
62 threads = self.filter(parent=NO_PARENT)
62 threads = self.filter(parent=NO_PARENT)
63 threads = list(threads.order_by('-last_edit_time'))
63 threads = threads.order_by('-last_edit_time')
64
64
65 if page != self.ALL_PAGES:
65 if page != self.ALL_PAGES:
66 thread_count = len(threads)
66 thread_count = len(threads)
67
67
68 if page < self.get_thread_page_count(tag=tag):
68 if page < self.get_thread_page_count(tag=tag):
69 start_thread = page * settings.THREADS_PER_PAGE
69 start_thread = page * settings.THREADS_PER_PAGE
70 end_thread = min(start_thread + settings.THREADS_PER_PAGE,
70 end_thread = min(start_thread + settings.THREADS_PER_PAGE,
71 thread_count)
71 thread_count)
72 threads = threads[start_thread:end_thread]
72 threads = threads[start_thread:end_thread]
73
73
74 return threads
74 return threads
75
75
76 def get_thread(self, opening_post_id):
76 def get_thread(self, opening_post_id):
77 opening_post = self.get(id=opening_post_id)
77 opening_post = self.get(id=opening_post_id)
78
78
79 if opening_post.parent == NO_PARENT:
79 if opening_post.parent == NO_PARENT:
80 replies = self.filter(parent=opening_post_id)
80 replies = self.filter(parent=opening_post_id)
81
81
82 thread = [opening_post]
82 thread = [opening_post]
83 thread.extend(replies)
83 thread.extend(replies)
84
84
85 return thread
85 return thread
86
86
87 def exists(self, post_id):
87 def exists(self, post_id):
88 posts = self.filter(id=post_id)
88 posts = self.filter(id=post_id)
89
89
90 return len(posts) > 0
90 return posts.count() > 0
91
91
92 def get_thread_page_count(self, tag=None):
92 def get_thread_page_count(self, tag=None):
93 if tag:
93 if tag:
94 threads = self.filter(parent=NO_PARENT, tags=tag)
94 threads = self.filter(parent=NO_PARENT, tags=tag)
95 else:
95 else:
96 threads = self.filter(parent=NO_PARENT)
96 threads = self.filter(parent=NO_PARENT)
97
97
98 return int(math.ceil(len(threads) / float(settings.THREADS_PER_PAGE)))
98 return int(math.ceil(threads.count() / float(
99 settings.THREADS_PER_PAGE)))
99
100
100 def _delete_old_threads(self):
101 def _delete_old_threads(self):
101 """
102 """
102 Preserves maximum thread count. If there are too many threads,
103 Preserves maximum thread count. If there are too many threads,
103 delete the old ones.
104 delete the old ones.
104 """
105 """
105
106
106 # TODO Try to find a better way to get the active thread count.
107
108 # TODO Move old threads to the archive instead of deleting them.
107 # TODO Move old threads to the archive instead of deleting them.
109 # Maybe make some 'old' field in the model to indicate the thread
108 # Maybe make some 'old' field in the model to indicate the thread
110 # must not be shown and be able for replying.
109 # must not be shown and be able for replying.
111
110
112 threads = self.get_threads()
111 threads = self.get_threads()
113 thread_count = len(threads)
112 thread_count = len(threads)
114
113
115 if thread_count > settings.MAX_THREAD_COUNT:
114 if thread_count > settings.MAX_THREAD_COUNT:
116 num_threads_to_delete = thread_count - settings.MAX_THREAD_COUNT
115 num_threads_to_delete = thread_count - settings.MAX_THREAD_COUNT
117 old_threads = threads[-num_threads_to_delete:]
116 old_threads = threads[thread_count - num_threads_to_delete:]
118
117
119 for thread in old_threads:
118 for thread in old_threads:
120 self.delete_post(thread)
119 self.delete_post(thread)
121
120
122 def _bump_thread(self, thread_id):
121 def _bump_thread(self, thread_id):
123 thread = self.get(id=thread_id)
122 thread = self.get(id=thread_id)
124
123
125 if thread.can_bump():
124 if thread.can_bump():
126 thread.last_edit_time = timezone.now()
125 thread.last_edit_time = timezone.now()
127 thread.save()
126 thread.save()
128
127
129
128
130 class TagManager(models.Manager):
129 class TagManager(models.Manager):
131 def get_not_empty_tags(self):
130 def get_not_empty_tags(self):
132 all_tags = self.all().order_by('name')
131 all_tags = self.all().order_by('name')
133 tags = []
132 tags = []
134 for tag in all_tags:
133 for tag in all_tags:
135 if not tag.is_empty():
134 if not tag.is_empty():
136 tags.append(tag)
135 tags.append(tag)
137
136
138 return tags
137 return tags
139
138
140 def get_popular_tags(self):
139 def get_popular_tags(self):
141 all_tags = self.get_not_empty_tags()
140 all_tags = self.get_not_empty_tags()
142
141
143 sorted_tags = sorted(all_tags, key=lambda tag: tag.get_popularity(),
142 sorted_tags = sorted(all_tags, key=lambda tag: tag.get_popularity(),
144 reverse=True)
143 reverse=True)
145
144
146 return sorted_tags[:settings.POPULAR_TAGS]
145 return sorted_tags[:settings.POPULAR_TAGS]
147
146
148
147
149 class Tag(models.Model):
148 class Tag(models.Model):
150 """
149 """
151 A tag is a text node assigned to the post. The tag serves as a board
150 A tag is a text node assigned to the post. The tag serves as a board
152 section. There can be multiple tags for each message
151 section. There can be multiple tags for each message
153 """
152 """
154
153
154 OPENING_POST_WEIGHT = 5
155
155 objects = TagManager()
156 objects = TagManager()
156
157
157 name = models.CharField(max_length=100)
158 name = models.CharField(max_length=100)
158 # TODO Connect the tag to its posts to check the number of threads for
159 # TODO Connect the tag to its posts to check the number of threads for
159 # the tag.
160 # the tag.
160
161
161 def __unicode__(self):
162 def __unicode__(self):
162 return self.name
163 return self.name
163
164
164 def is_empty(self):
165 def is_empty(self):
165 return self.get_post_count() == 0
166 return self.get_post_count() == 0
166
167
167 def get_post_count(self):
168 def get_post_count(self):
168 posts_with_tag = Post.objects.get_threads(tag=self)
169 posts_with_tag = Post.objects.get_threads(tag=self)
169 return len(posts_with_tag)
170 return posts_with_tag.count()
170
171
171 def get_popularity(self):
172 def get_popularity(self):
172 posts_with_tag = Post.objects.get_threads(tag=self)
173 posts_with_tag = Post.objects.get_threads(tag=self)
173 reply_count = 0
174 reply_count = 0
174 for post in posts_with_tag:
175 for post in posts_with_tag:
175 reply_count += post.get_reply_count()
176 reply_count += post.get_reply_count()
177 reply_count += self.OPENING_POST_WEIGHT
176
178
177 return reply_count
179 return reply_count
178
180
179
181
180 class Post(models.Model):
182 class Post(models.Model):
181 """A post is a message."""
183 """A post is a message."""
182
184
183 IMAGES_DIRECTORY = 'images/'
185 IMAGES_DIRECTORY = 'images/'
184 FILE_EXTENSION_DELIMITER = '.'
186 FILE_EXTENSION_DELIMITER = '.'
185
187
186 objects = PostManager()
188 objects = PostManager()
187
189
188 def _update_image_filename(self, filename):
190 def _update_image_filename(self, filename):
189 """Get unique image filename"""
191 """Get unique image filename"""
190
192
191 path = self.IMAGES_DIRECTORY
193 path = self.IMAGES_DIRECTORY
192 new_name = str(int(time.mktime(time.gmtime())))
194 new_name = str(int(time.mktime(time.gmtime())))
193 new_name += str(int(random() * 1000))
195 new_name += str(int(random() * 1000))
194 new_name += self.FILE_EXTENSION_DELIMITER
196 new_name += self.FILE_EXTENSION_DELIMITER
195 new_name += filename.split(self.FILE_EXTENSION_DELIMITER)[-1:][0]
197 new_name += filename.split(self.FILE_EXTENSION_DELIMITER)[-1:][0]
196
198
197 return os.path.join(path, new_name)
199 return os.path.join(path, new_name)
198
200
199 title = models.CharField(max_length=50)
201 title = models.CharField(max_length=50)
200 pub_time = models.DateTimeField()
202 pub_time = models.DateTimeField()
201 text = MarkupField(default_markup_type='markdown', escape_html=True)
203 text = MarkupField(default_markup_type='markdown', escape_html=True)
202 image = thumbs.ImageWithThumbsField(upload_to=_update_image_filename,
204 image = thumbs.ImageWithThumbsField(upload_to=_update_image_filename,
203 blank=True, sizes=((200, 150),))
205 blank=True, sizes=((200, 150),))
204 poster_ip = models.IPAddressField()
206 poster_ip = models.IPAddressField()
205 poster_user_agent = models.TextField()
207 poster_user_agent = models.TextField()
206 parent = models.BigIntegerField()
208 parent = models.BigIntegerField()
207 tags = models.ManyToManyField(Tag)
209 tags = models.ManyToManyField(Tag)
208 last_edit_time = models.DateTimeField()
210 last_edit_time = models.DateTimeField()
209
211
210 regex_pretty = re.compile(r'^\d(0)+$')
212 regex_pretty = re.compile(r'^\d(0)+$')
211 regex_same = re.compile(r'^(.)\1+$')
213 regex_same = re.compile(r'^(.)\1+$')
212
214
213 def __unicode__(self):
215 def __unicode__(self):
214 return self.title + ' (' + self.text.raw + ')'
216 return self.title + ' (' + self.text.raw + ')'
215
217
216 def _get_replies(self):
218 def _get_replies(self):
217 return Post.objects.filter(parent=self.id)
219 return Post.objects.filter(parent=self.id)
218
220
219 def get_reply_count(self):
221 def get_reply_count(self):
220 return len(self._get_replies())
222 return self._get_replies().count()
221
223
222 def get_images_count(self):
224 def get_images_count(self):
223 images_count = 1 if self.image else 0
225 images_count = 1 if self.image else 0
224 for reply in self._get_replies():
226 for reply in self._get_replies():
225 if reply.image:
227 if reply.image:
226 images_count += 1
228 images_count += 1
227
229
228 return images_count
230 return images_count
229
231
230 def get_gets_count(self):
232 def get_gets_count(self):
231 gets_count = 1 if self.is_get() else 0
233 gets_count = 1 if self.is_get() else 0
232 for reply in self._get_replies():
234 for reply in self._get_replies():
233 if reply.is_get():
235 if reply.is_get():
234 gets_count += 1
236 gets_count += 1
235
237
236 return gets_count
238 return gets_count
237
239
238 def is_get(self):
240 def is_get(self):
239 """If the post has pretty id (1, 1000, 77777), than it is called GET"""
241 """If the post has pretty id (1, 1000, 77777), than it is called GET"""
240
242
241 first = self.id == 1
243 first = self.id == 1
242
244
243 id_str = str(self.id)
245 id_str = str(self.id)
244 pretty = self.regex_pretty.match(id_str)
246 pretty = self.regex_pretty.match(id_str)
245 same_digits = self.regex_same.match(id_str)
247 same_digits = self.regex_same.match(id_str)
246
248
247 return first or pretty or same_digits
249 return first or pretty or same_digits
248
250
249 def can_bump(self):
251 def can_bump(self):
250 """Check if the thread can be bumped by replying"""
252 """Check if the thread can be bumped by replying"""
251
253
252 replies_count = len(Post.objects.get_thread(self.id))
254 replies_count = len(Post.objects.get_thread(self.id))
253
255
254 return replies_count <= settings.MAX_POSTS_PER_THREAD
256 return replies_count <= settings.MAX_POSTS_PER_THREAD
255
257
256
258
257 class Admin(models.Model):
259 class Admin(models.Model):
258 """
260 """
259 Model for admin users
261 Model for admin users
260 """
262 """
261 name = models.CharField(max_length=100)
263 name = models.CharField(max_length=100)
262 password = models.CharField(max_length=100)
264 password = models.CharField(max_length=100)
263
265
264 def __unicode__(self):
266 def __unicode__(self):
265 return self.name + '/' + '*' * len(self.password) No newline at end of file
267 return self.name + '/' + '*' * len(self.password)
@@ -1,186 +1,186 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'
35 LANGUAGE_CODE = '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 )
141 )
142
142
143 # A sample logging configuration. The only tangible logging
143 # A sample logging configuration. The only tangible logging
144 # performed by this configuration is to send an email to
144 # performed by this configuration is to send an email to
145 # the site admins on every HTTP 500 error when DEBUG=False.
145 # the site admins on every HTTP 500 error when DEBUG=False.
146 # See http://docs.djangoproject.com/en/dev/topics/logging for
146 # See http://docs.djangoproject.com/en/dev/topics/logging for
147 # more details on how to customize your logging configuration.
147 # more details on how to customize your logging configuration.
148 LOGGING = {
148 LOGGING = {
149 'version': 1,
149 'version': 1,
150 'disable_existing_loggers': False,
150 'disable_existing_loggers': False,
151 'filters': {
151 'filters': {
152 'require_debug_false': {
152 'require_debug_false': {
153 '()': 'django.utils.log.RequireDebugFalse'
153 '()': 'django.utils.log.RequireDebugFalse'
154 }
154 }
155 },
155 },
156 'handlers': {
156 'handlers': {
157 'mail_admins': {
157 'mail_admins': {
158 'level': 'ERROR',
158 'level': 'ERROR',
159 'filters': ['require_debug_false'],
159 'filters': ['require_debug_false'],
160 'class': 'django.utils.log.AdminEmailHandler'
160 'class': 'django.utils.log.AdminEmailHandler'
161 }
161 }
162 },
162 },
163 'loggers': {
163 'loggers': {
164 'django.request': {
164 'django.request': {
165 'handlers': ['mail_admins'],
165 'handlers': ['mail_admins'],
166 'level': 'ERROR',
166 'level': 'ERROR',
167 'propagate': True,
167 'propagate': True,
168 },
168 },
169 }
169 }
170 }
170 }
171
171
172 MARKUP_FIELD_TYPES = (
172 MARKUP_FIELD_TYPES = (
173 ('markdown', markdown_extended),
173 ('markdown', markdown_extended),
174 )
174 )
175 # Custom imageboard settings
175 # Custom imageboard settings
176 MAX_POSTS_PER_THREAD = 10 # Thread bumplimit
176 MAX_POSTS_PER_THREAD = 10 # Thread bumplimit
177 MAX_THREAD_COUNT = 500 # Old threads will be deleted to preserve this count
177 MAX_THREAD_COUNT = 500 # Old threads will be deleted to preserve this count
178 THREADS_PER_PAGE = 10
178 THREADS_PER_PAGE = 10
179 SITE_NAME = 'Neboard'
179 SITE_NAME = 'Neboard'
180
180
181 THEMES = [
181 THEMES = [
182 ('md', 'Mystic Dark'),
182 ('md', 'Mystic Dark'),
183 ('sw', 'Snow White') ]
183 ('sw', 'Snow White') ]
184 DEFAULT_THEME = 'md'
184 DEFAULT_THEME = 'md'
185
185
186 POPULAR_TAGS=10 No newline at end of file
186 POPULAR_TAGS = 10 No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now