##// END OF EJS Templates
Use transactions only in views that need them
neko259 -
r335:172f5ae7 default
parent child Browse files
Show More
@@ -1,485 +1,492 b''
1 import hashlib
1 import hashlib
2 import string
2 import string
3 from django.core import serializers
3 from django.core import serializers
4 from django.core.urlresolvers import reverse
4 from django.core.urlresolvers import reverse
5 from django.http import HttpResponseRedirect
5 from django.http import HttpResponseRedirect
6 from django.http.response import HttpResponse
6 from django.http.response import HttpResponse
7 from django.template import RequestContext
7 from django.template import RequestContext
8 from django.shortcuts import render, redirect, get_object_or_404
8 from django.shortcuts import render, redirect, get_object_or_404
9 from django.utils import timezone
9 from django.utils import timezone
10 from django.db import transaction
10
11
11 from boards import forms
12 from boards import forms
12 import boards
13 import boards
13 from boards import utils
14 from boards import utils
14 from boards.forms import ThreadForm, PostForm, SettingsForm, PlainErrorList, \
15 from boards.forms import ThreadForm, PostForm, SettingsForm, PlainErrorList, \
15 ThreadCaptchaForm, PostCaptchaForm, LoginForm, ModeratorSettingsForm
16 ThreadCaptchaForm, PostCaptchaForm, LoginForm, ModeratorSettingsForm
16
17
17 from boards.models import Post, Tag, Ban, User, RANK_USER, SETTING_MODERATE, \
18 from boards.models import Post, Tag, Ban, User, RANK_USER, SETTING_MODERATE, \
18 REGEX_REPLY
19 REGEX_REPLY
19 from boards import authors
20 from boards import authors
20 from boards.utils import get_client_ip
21 from boards.utils import get_client_ip
21 import neboard
22 import neboard
22 import re
23 import re
23
24
24
25
25 def index(request, page=0):
26 def index(request, page=0):
26 context = _init_default_context(request)
27 context = _init_default_context(request)
27
28
28 if utils.need_include_captcha(request):
29 if utils.need_include_captcha(request):
29 threadFormClass = ThreadCaptchaForm
30 threadFormClass = ThreadCaptchaForm
30 kwargs = {'request': request}
31 kwargs = {'request': request}
31 else:
32 else:
32 threadFormClass = ThreadForm
33 threadFormClass = ThreadForm
33 kwargs = {}
34 kwargs = {}
34
35
35 if request.method == 'POST':
36 if request.method == 'POST':
36 form = threadFormClass(request.POST, request.FILES,
37 form = threadFormClass(request.POST, request.FILES,
37 error_class=PlainErrorList, **kwargs)
38 error_class=PlainErrorList, **kwargs)
38 form.session = request.session
39 form.session = request.session
39
40
40 if form.is_valid():
41 if form.is_valid():
41 return _new_post(request, form)
42 return _new_post(request, form)
42 if form.need_to_ban:
43 if form.need_to_ban:
43 # Ban user because he is suspected to be a bot
44 # Ban user because he is suspected to be a bot
44 _ban_current_user(request)
45 _ban_current_user(request)
45 else:
46 else:
46 form = threadFormClass(error_class=PlainErrorList, **kwargs)
47 form = threadFormClass(error_class=PlainErrorList, **kwargs)
47
48
48 threads = []
49 threads = []
49 for thread in Post.objects.get_threads(page=int(page)):
50 for thread in Post.objects.get_threads(page=int(page)):
50 threads.append({
51 threads.append({
51 'thread': thread,
52 'thread': thread,
52 'bumpable': thread.can_bump(),
53 'bumpable': thread.can_bump(),
53 'last_replies': thread.get_last_replies(),
54 'last_replies': thread.get_last_replies(),
54 })
55 })
55
56
56 context['threads'] = None if len(threads) == 0 else threads
57 context['threads'] = None if len(threads) == 0 else threads
57 context['form'] = form
58 context['form'] = form
58 context['pages'] = range(Post.objects.get_thread_page_count())
59 context['pages'] = range(Post.objects.get_thread_page_count())
59
60
60 return render(request, 'boards/posting_general.html',
61 return render(request, 'boards/posting_general.html',
61 context)
62 context)
62
63
63
64
65 @transaction.commit_on_success
64 def _new_post(request, form, thread_id=boards.models.NO_PARENT):
66 def _new_post(request, form, thread_id=boards.models.NO_PARENT):
65 """Add a new post (in thread or as a reply)."""
67 """Add a new post (in thread or as a reply)."""
66
68
67 ip = get_client_ip(request)
69 ip = get_client_ip(request)
68 is_banned = Ban.objects.filter(ip=ip).exists()
70 is_banned = Ban.objects.filter(ip=ip).exists()
69
71
70 if is_banned:
72 if is_banned:
71 return redirect(you_are_banned)
73 return redirect(you_are_banned)
72
74
73 data = form.cleaned_data
75 data = form.cleaned_data
74
76
75 title = data['title']
77 title = data['title']
76 text = data['text']
78 text = data['text']
77
79
78 text = _remove_invalid_links(text)
80 text = _remove_invalid_links(text)
79
81
80 if 'image' in data.keys():
82 if 'image' in data.keys():
81 image = data['image']
83 image = data['image']
82 else:
84 else:
83 image = None
85 image = None
84
86
85 tags = []
87 tags = []
86
88
87 new_thread = thread_id == boards.models.NO_PARENT
89 new_thread = thread_id == boards.models.NO_PARENT
88 if new_thread:
90 if new_thread:
89 tag_strings = data['tags']
91 tag_strings = data['tags']
90
92
91 if tag_strings:
93 if tag_strings:
92 tag_strings = tag_strings.split(' ')
94 tag_strings = tag_strings.split(' ')
93 for tag_name in tag_strings:
95 for tag_name in tag_strings:
94 tag_name = string.lower(tag_name.strip())
96 tag_name = string.lower(tag_name.strip())
95 if len(tag_name) > 0:
97 if len(tag_name) > 0:
96 tag, created = Tag.objects.get_or_create(name=tag_name)
98 tag, created = Tag.objects.get_or_create(name=tag_name)
97 tags.append(tag)
99 tags.append(tag)
98
100
99 linked_tags = tag.get_linked_tags()
101 linked_tags = tag.get_linked_tags()
100 if len(linked_tags) > 0:
102 if len(linked_tags) > 0:
101 tags.extend(linked_tags)
103 tags.extend(linked_tags)
102
104
103 op = None if thread_id == boards.models.NO_PARENT else \
105 op = None if thread_id == boards.models.NO_PARENT else \
104 get_object_or_404(Post, id=thread_id)
106 get_object_or_404(Post, id=thread_id)
105 post = Post.objects.create_post(title=title, text=text, ip=ip,
107 post = Post.objects.create_post(title=title, text=text, ip=ip,
106 thread=op, image=image,
108 thread=op, image=image,
107 tags=tags, user=_get_user(request))
109 tags=tags, user=_get_user(request))
108
110
109 thread_to_show = (post.id if new_thread else thread_id)
111 thread_to_show = (post.id if new_thread else thread_id)
110
112
111 if new_thread:
113 if new_thread:
112 return redirect(thread, post_id=thread_to_show)
114 return redirect(thread, post_id=thread_to_show)
113 else:
115 else:
114 return redirect(reverse(thread, kwargs={'post_id': thread_to_show}) +
116 return redirect(reverse(thread, kwargs={'post_id': thread_to_show}) +
115 '#' + str(post.id))
117 '#' + str(post.id))
116
118
117
119
118 def tag(request, tag_name, page=0):
120 def tag(request, tag_name, page=0):
119 """
121 """
120 Get all tag threads. Threads are split in pages, so some page is
122 Get all tag threads. Threads are split in pages, so some page is
121 requested. Default page is 0.
123 requested. Default page is 0.
122 """
124 """
123
125
124 tag = get_object_or_404(Tag, name=tag_name)
126 tag = get_object_or_404(Tag, name=tag_name)
125 threads = []
127 threads = []
126 for thread in Post.objects.get_threads(tag=tag, page=int(page)):
128 for thread in Post.objects.get_threads(tag=tag, page=int(page)):
127 threads.append({
129 threads.append({
128 'thread': thread,
130 'thread': thread,
129 'bumpable': thread.can_bump(),
131 'bumpable': thread.can_bump(),
130 'last_replies': thread.get_last_replies(),
132 'last_replies': thread.get_last_replies(),
131 })
133 })
132
134
133 if request.method == 'POST':
135 if request.method == 'POST':
134 form = ThreadForm(request.POST, request.FILES,
136 form = ThreadForm(request.POST, request.FILES,
135 error_class=PlainErrorList)
137 error_class=PlainErrorList)
136 form.session = request.session
138 form.session = request.session
137
139
138 if form.is_valid():
140 if form.is_valid():
139 return _new_post(request, form)
141 return _new_post(request, form)
140 if form.need_to_ban:
142 if form.need_to_ban:
141 # Ban user because he is suspected to be a bot
143 # Ban user because he is suspected to be a bot
142 _ban_current_user(request)
144 _ban_current_user(request)
143 else:
145 else:
144 form = forms.ThreadForm(initial={'tags': tag_name},
146 form = forms.ThreadForm(initial={'tags': tag_name},
145 error_class=PlainErrorList)
147 error_class=PlainErrorList)
146
148
147 context = _init_default_context(request)
149 context = _init_default_context(request)
148 context['threads'] = None if len(threads) == 0 else threads
150 context['threads'] = None if len(threads) == 0 else threads
149 context['tag'] = tag
151 context['tag'] = tag
150 context['pages'] = range(Post.objects.get_thread_page_count(tag=tag))
152 context['pages'] = range(Post.objects.get_thread_page_count(tag=tag))
151
153
152 context['form'] = form
154 context['form'] = form
153
155
154 return render(request, 'boards/posting_general.html',
156 return render(request, 'boards/posting_general.html',
155 context)
157 context)
156
158
157
159
158 def thread(request, post_id):
160 def thread(request, post_id):
159 """Get all thread posts"""
161 """Get all thread posts"""
160
162
161 if utils.need_include_captcha(request):
163 if utils.need_include_captcha(request):
162 postFormClass = PostCaptchaForm
164 postFormClass = PostCaptchaForm
163 kwargs = {'request': request}
165 kwargs = {'request': request}
164 else:
166 else:
165 postFormClass = PostForm
167 postFormClass = PostForm
166 kwargs = {}
168 kwargs = {}
167
169
168 if request.method == 'POST':
170 if request.method == 'POST':
169 form = postFormClass(request.POST, request.FILES,
171 form = postFormClass(request.POST, request.FILES,
170 error_class=PlainErrorList, **kwargs)
172 error_class=PlainErrorList, **kwargs)
171 form.session = request.session
173 form.session = request.session
172
174
173 if form.is_valid():
175 if form.is_valid():
174 return _new_post(request, form, post_id)
176 return _new_post(request, form, post_id)
175 if form.need_to_ban:
177 if form.need_to_ban:
176 # Ban user because he is suspected to be a bot
178 # Ban user because he is suspected to be a bot
177 _ban_current_user(request)
179 _ban_current_user(request)
178 else:
180 else:
179 form = postFormClass(error_class=PlainErrorList, **kwargs)
181 form = postFormClass(error_class=PlainErrorList, **kwargs)
180
182
181 posts = Post.objects.get_thread(post_id)
183 posts = Post.objects.get_thread(post_id)
182
184
183 context = _init_default_context(request)
185 context = _init_default_context(request)
184
186
185 context['posts'] = posts
187 context['posts'] = posts
186 context['form'] = form
188 context['form'] = form
187 context['bumpable'] = posts[0].can_bump()
189 context['bumpable'] = posts[0].can_bump()
188 if context['bumpable']:
190 if context['bumpable']:
189 context['posts_left'] = neboard.settings.MAX_POSTS_PER_THREAD - len(
191 context['posts_left'] = neboard.settings.MAX_POSTS_PER_THREAD - len(
190 posts)
192 posts)
191 context['bumplimit_progress'] = str(
193 context['bumplimit_progress'] = str(
192 float(context['posts_left']) /
194 float(context['posts_left']) /
193 neboard.settings.MAX_POSTS_PER_THREAD * 100)
195 neboard.settings.MAX_POSTS_PER_THREAD * 100)
194
196
195 return render(request, 'boards/thread.html', context)
197 return render(request, 'boards/thread.html', context)
196
198
197
199
198 def login(request):
200 def login(request):
199 """Log in with user id"""
201 """Log in with user id"""
200
202
201 context = _init_default_context(request)
203 context = _init_default_context(request)
202
204
203 if request.method == 'POST':
205 if request.method == 'POST':
204 form = LoginForm(request.POST, request.FILES,
206 form = LoginForm(request.POST, request.FILES,
205 error_class=PlainErrorList)
207 error_class=PlainErrorList)
206 form.session = request.session
208 form.session = request.session
207
209
208 if form.is_valid():
210 if form.is_valid():
209 user = User.objects.get(user_id=form.cleaned_data['user_id'])
211 user = User.objects.get(user_id=form.cleaned_data['user_id'])
210 request.session['user_id'] = user.id
212 request.session['user_id'] = user.id
211 return redirect(index)
213 return redirect(index)
212
214
213 else:
215 else:
214 form = LoginForm()
216 form = LoginForm()
215
217
216 context['form'] = form
218 context['form'] = form
217
219
218 return render(request, 'boards/login.html', context)
220 return render(request, 'boards/login.html', context)
219
221
220
222
221 def settings(request):
223 def settings(request):
222 """User's settings"""
224 """User's settings"""
223
225
224 context = _init_default_context(request)
226 context = _init_default_context(request)
225 user = _get_user(request)
227 user = _get_user(request)
226 is_moderator = user.is_moderator()
228 is_moderator = user.is_moderator()
227
229
228 if request.method == 'POST':
230 if request.method == 'POST':
229 if is_moderator:
231 with transaction.commit_on_success():
230 form = ModeratorSettingsForm(request.POST,
232 if is_moderator:
231 error_class=PlainErrorList)
233 form = ModeratorSettingsForm(request.POST,
232 else:
234 error_class=PlainErrorList)
233 form = SettingsForm(request.POST, error_class=PlainErrorList)
235 else:
236 form = SettingsForm(request.POST, error_class=PlainErrorList)
234
237
235 if form.is_valid():
238 if form.is_valid():
236 selected_theme = form.cleaned_data['theme']
239 selected_theme = form.cleaned_data['theme']
237
240
238 user.save_setting('theme', selected_theme)
241 user.save_setting('theme', selected_theme)
239
242
240 if is_moderator:
243 if is_moderator:
241 moderate = form.cleaned_data['moderate']
244 moderate = form.cleaned_data['moderate']
242 user.save_setting(SETTING_MODERATE, moderate)
245 user.save_setting(SETTING_MODERATE, moderate)
243
246
244 return redirect(settings)
247 return redirect(settings)
245 else:
248 else:
246 selected_theme = _get_theme(request)
249 selected_theme = _get_theme(request)
247
250
248 if is_moderator:
251 if is_moderator:
249 form = ModeratorSettingsForm(initial={'theme': selected_theme,
252 form = ModeratorSettingsForm(initial={'theme': selected_theme,
250 'moderate': context['moderator']},
253 'moderate': context['moderator']},
251 error_class=PlainErrorList)
254 error_class=PlainErrorList)
252 else:
255 else:
253 form = SettingsForm(initial={'theme': selected_theme},
256 form = SettingsForm(initial={'theme': selected_theme},
254 error_class=PlainErrorList)
257 error_class=PlainErrorList)
255
258
256 context['form'] = form
259 context['form'] = form
257
260
258 return render(request, 'boards/settings.html', context)
261 return render(request, 'boards/settings.html', context)
259
262
260
263
261 def all_tags(request):
264 def all_tags(request):
262 """All tags list"""
265 """All tags list"""
263
266
264 context = _init_default_context(request)
267 context = _init_default_context(request)
265 context['all_tags'] = Tag.objects.get_not_empty_tags()
268 context['all_tags'] = Tag.objects.get_not_empty_tags()
266
269
267 return render(request, 'boards/tags.html', context)
270 return render(request, 'boards/tags.html', context)
268
271
269
272
270 def jump_to_post(request, post_id):
273 def jump_to_post(request, post_id):
271 """Determine thread in which the requested post is and open it's page"""
274 """Determine thread in which the requested post is and open it's page"""
272
275
273 post = get_object_or_404(Post, id=post_id)
276 post = get_object_or_404(Post, id=post_id)
274
277
275 if not post.thread:
278 if not post.thread:
276 return redirect(thread, post_id=post.id)
279 return redirect(thread, post_id=post.id)
277 else:
280 else:
278 return redirect(reverse(thread, kwargs={'post_id': post.thread.id})
281 return redirect(reverse(thread, kwargs={'post_id': post.thread.id})
279 + '#' + str(post.id))
282 + '#' + str(post.id))
280
283
281
284
282 def authors(request):
285 def authors(request):
283 """Show authors list"""
286 """Show authors list"""
284
287
285 context = _init_default_context(request)
288 context = _init_default_context(request)
286 context['authors'] = boards.authors.authors
289 context['authors'] = boards.authors.authors
287
290
288 return render(request, 'boards/authors.html', context)
291 return render(request, 'boards/authors.html', context)
289
292
290
293
294 @transaction.commit_on_success
291 def delete(request, post_id):
295 def delete(request, post_id):
292 """Delete post"""
296 """Delete post"""
293
297
294 user = _get_user(request)
298 user = _get_user(request)
295 post = get_object_or_404(Post, id=post_id)
299 post = get_object_or_404(Post, id=post_id)
296
300
297 if user.is_moderator():
301 if user.is_moderator():
298 # TODO Show confirmation page before deletion
302 # TODO Show confirmation page before deletion
299 Post.objects.delete_post(post)
303 Post.objects.delete_post(post)
300
304
301 if not post.thread:
305 if not post.thread:
302 return _redirect_to_next(request)
306 return _redirect_to_next(request)
303 else:
307 else:
304 return redirect(thread, post_id=post.thread.id)
308 return redirect(thread, post_id=post.thread.id)
305
309
306
310
311 @transaction.commit_on_success
307 def ban(request, post_id):
312 def ban(request, post_id):
308 """Ban user"""
313 """Ban user"""
309
314
310 user = _get_user(request)
315 user = _get_user(request)
311 post = get_object_or_404(Post, id=post_id)
316 post = get_object_or_404(Post, id=post_id)
312
317
313 if user.is_moderator():
318 if user.is_moderator():
314 # TODO Show confirmation page before ban
319 # TODO Show confirmation page before ban
315 Ban.objects.get_or_create(ip=post.poster_ip)
320 Ban.objects.get_or_create(ip=post.poster_ip)
316
321
317 return _redirect_to_next(request)
322 return _redirect_to_next(request)
318
323
319
324
320 def you_are_banned(request):
325 def you_are_banned(request):
321 """Show the page that notifies that user is banned"""
326 """Show the page that notifies that user is banned"""
322
327
323 context = _init_default_context(request)
328 context = _init_default_context(request)
324 return render(request, 'boards/staticpages/banned.html', context)
329 return render(request, 'boards/staticpages/banned.html', context)
325
330
326
331
327 def page_404(request):
332 def page_404(request):
328 """Show page 404 (not found error)"""
333 """Show page 404 (not found error)"""
329
334
330 context = _init_default_context(request)
335 context = _init_default_context(request)
331 return render(request, 'boards/404.html', context)
336 return render(request, 'boards/404.html', context)
332
337
333
338
339 @transaction.commit_on_success
334 def tag_subscribe(request, tag_name):
340 def tag_subscribe(request, tag_name):
335 """Add tag to favorites"""
341 """Add tag to favorites"""
336
342
337 user = _get_user(request)
343 user = _get_user(request)
338 tag = get_object_or_404(Tag, name=tag_name)
344 tag = get_object_or_404(Tag, name=tag_name)
339
345
340 if not tag in user.fav_tags.all():
346 if not tag in user.fav_tags.all():
341 user.add_tag(tag)
347 user.add_tag(tag)
342
348
343 return _redirect_to_next(request)
349 return _redirect_to_next(request)
344
350
345
351
352 @transaction.commit_on_success
346 def tag_unsubscribe(request, tag_name):
353 def tag_unsubscribe(request, tag_name):
347 """Remove tag from favorites"""
354 """Remove tag from favorites"""
348
355
349 user = _get_user(request)
356 user = _get_user(request)
350 tag = get_object_or_404(Tag, name=tag_name)
357 tag = get_object_or_404(Tag, name=tag_name)
351
358
352 if tag in user.fav_tags.all():
359 if tag in user.fav_tags.all():
353 user.remove_tag(tag)
360 user.remove_tag(tag)
354
361
355 return _redirect_to_next(request)
362 return _redirect_to_next(request)
356
363
357
364
358 def static_page(request, name):
365 def static_page(request, name):
359 """Show a static page that needs only tags list and a CSS"""
366 """Show a static page that needs only tags list and a CSS"""
360
367
361 context = _init_default_context(request)
368 context = _init_default_context(request)
362 return render(request, 'boards/staticpages/' + name + '.html', context)
369 return render(request, 'boards/staticpages/' + name + '.html', context)
363
370
364
371
365 def api_get_post(request, post_id):
372 def api_get_post(request, post_id):
366 """
373 """
367 Get the JSON of a post. This can be
374 Get the JSON of a post. This can be
368 used as and API for external clients.
375 used as and API for external clients.
369 """
376 """
370
377
371 post = get_object_or_404(Post, id=post_id)
378 post = get_object_or_404(Post, id=post_id)
372
379
373 json = serializers.serialize("json", [post], fields=(
380 json = serializers.serialize("json", [post], fields=(
374 "pub_time", "_text_rendered", "title", "text", "image",
381 "pub_time", "_text_rendered", "title", "text", "image",
375 "image_width", "image_height", "replies", "tags"
382 "image_width", "image_height", "replies", "tags"
376 ))
383 ))
377
384
378 return HttpResponse(content=json)
385 return HttpResponse(content=json)
379
386
380
387
381 def get_post(request, post_id):
388 def get_post(request, post_id):
382 """Get the html of a post. Used for popups."""
389 """Get the html of a post. Used for popups."""
383
390
384 post = get_object_or_404(Post, id=post_id)
391 post = get_object_or_404(Post, id=post_id)
385
392
386 context = RequestContext(request)
393 context = RequestContext(request)
387 context["post"] = post
394 context["post"] = post
388
395
389 return render(request, 'boards/post.html', context)
396 return render(request, 'boards/post.html', context)
390
397
391
398
392 def _get_theme(request, user=None):
399 def _get_theme(request, user=None):
393 """Get user's CSS theme"""
400 """Get user's CSS theme"""
394
401
395 if not user:
402 if not user:
396 user = _get_user(request)
403 user = _get_user(request)
397 theme = user.get_setting('theme')
404 theme = user.get_setting('theme')
398 if not theme:
405 if not theme:
399 theme = neboard.settings.DEFAULT_THEME
406 theme = neboard.settings.DEFAULT_THEME
400
407
401 return theme
408 return theme
402
409
403
410
404 def _init_default_context(request):
411 def _init_default_context(request):
405 """Create context with default values that are used in most views"""
412 """Create context with default values that are used in most views"""
406
413
407 context = RequestContext(request)
414 context = RequestContext(request)
408
415
409 user = _get_user(request)
416 user = _get_user(request)
410 context['user'] = user
417 context['user'] = user
411 context['tags'] = user.get_sorted_fav_tags()
418 context['tags'] = user.get_sorted_fav_tags()
412
419
413 theme = _get_theme(request, user)
420 theme = _get_theme(request, user)
414 context['theme'] = theme
421 context['theme'] = theme
415 context['theme_css'] = 'css/' + theme + '/base_page.css'
422 context['theme_css'] = 'css/' + theme + '/base_page.css'
416
423
417 # This shows the moderator panel
424 # This shows the moderator panel
418 moderate = user.get_setting(SETTING_MODERATE)
425 moderate = user.get_setting(SETTING_MODERATE)
419 if moderate == 'True':
426 if moderate == 'True':
420 context['moderator'] = user.is_moderator()
427 context['moderator'] = user.is_moderator()
421 else:
428 else:
422 context['moderator'] = False
429 context['moderator'] = False
423
430
424 return context
431 return context
425
432
426
433
427 def _get_user(request):
434 def _get_user(request):
428 """
435 """
429 Get current user from the session. If the user does not exist, create
436 Get current user from the session. If the user does not exist, create
430 a new one.
437 a new one.
431 """
438 """
432
439
433 session = request.session
440 session = request.session
434 if not 'user_id' in session:
441 if not 'user_id' in session:
435 request.session.save()
442 request.session.save()
436
443
437 md5 = hashlib.md5()
444 md5 = hashlib.md5()
438 md5.update(session.session_key)
445 md5.update(session.session_key)
439 new_id = md5.hexdigest()
446 new_id = md5.hexdigest()
440
447
441 time_now = timezone.now()
448 time_now = timezone.now()
442 user = User.objects.create(user_id=new_id, rank=RANK_USER,
449 user = User.objects.create(user_id=new_id, rank=RANK_USER,
443 registration_time=time_now)
450 registration_time=time_now)
444
451
445 session['user_id'] = user.id
452 session['user_id'] = user.id
446 else:
453 else:
447 user = User.objects.get(id=session['user_id'])
454 user = User.objects.get(id=session['user_id'])
448
455
449 return user
456 return user
450
457
451
458
452 def _redirect_to_next(request):
459 def _redirect_to_next(request):
453 """
460 """
454 If a 'next' parameter was specified, redirect to the next page. This is
461 If a 'next' parameter was specified, redirect to the next page. This is
455 used when the user is required to return to some page after the current
462 used when the user is required to return to some page after the current
456 view has finished its work.
463 view has finished its work.
457 """
464 """
458
465
459 if 'next' in request.GET:
466 if 'next' in request.GET:
460 next_page = request.GET['next']
467 next_page = request.GET['next']
461 return HttpResponseRedirect(next_page)
468 return HttpResponseRedirect(next_page)
462 else:
469 else:
463 return redirect(index)
470 return redirect(index)
464
471
465
472
466 def _ban_current_user(request):
473 def _ban_current_user(request):
467 """Add current user to the IP ban list"""
474 """Add current user to the IP ban list"""
468
475
469 ip = utils.get_client_ip(request)
476 ip = utils.get_client_ip(request)
470 Ban.objects.get_or_create(ip=ip)
477 Ban.objects.get_or_create(ip=ip)
471
478
472
479
473 def _remove_invalid_links(text):
480 def _remove_invalid_links(text):
474 """
481 """
475 Replace invalid links in posts so that they won't be parsed.
482 Replace invalid links in posts so that they won't be parsed.
476 Invalid links are links to non-existent posts
483 Invalid links are links to non-existent posts
477 """
484 """
478
485
479 for reply_number in re.finditer(REGEX_REPLY, text):
486 for reply_number in re.finditer(REGEX_REPLY, text):
480 post_id = reply_number.group(1)
487 post_id = reply_number.group(1)
481 post = Post.objects.filter(id=post_id)
488 post = Post.objects.filter(id=post_id)
482 if not post.exists():
489 if not post.exists():
483 text = string.replace(text, '>>' + id, id)
490 text = string.replace(text, '>>' + id, id)
484
491
485 return text
492 return text
@@ -1,241 +1,240 b''
1 # Django settings for neboard project.
1 # Django settings for neboard project.
2 import os
2 import os
3 from boards.mdx_neboard import markdown_extended
3 from boards.mdx_neboard import markdown_extended
4
4
5 DEBUG = True
5 DEBUG = True
6 TEMPLATE_DEBUG = DEBUG
6 TEMPLATE_DEBUG = DEBUG
7
7
8 ADMINS = (
8 ADMINS = (
9 # ('Your Name', 'your_email@example.com'),
9 # ('Your Name', 'your_email@example.com'),
10 ('admin', 'admin@example.com')
10 ('admin', 'admin@example.com')
11 )
11 )
12
12
13 MANAGERS = ADMINS
13 MANAGERS = ADMINS
14
14
15 DATABASES = {
15 DATABASES = {
16 'default': {
16 'default': {
17 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
17 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
18 'NAME': 'database.db', # Or path to database file if using sqlite3.
18 'NAME': 'database.db', # Or path to database file if using sqlite3.
19 'USER': '', # Not used with sqlite3.
19 'USER': '', # Not used with sqlite3.
20 'PASSWORD': '', # Not used with sqlite3.
20 'PASSWORD': '', # Not used with sqlite3.
21 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
21 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
22 'PORT': '', # Set to empty string for default. Not used with sqlite3.
22 'PORT': '', # Set to empty string for default. Not used with sqlite3.
23 'CONN_MAX_AGE': None,
23 'CONN_MAX_AGE': None,
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 = 'en'
35 LANGUAGE_CODE = 'en'
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 )
85 )
86
86
87 if DEBUG:
87 if DEBUG:
88 STATICFILES_STORAGE = \
88 STATICFILES_STORAGE = \
89 'django.contrib.staticfiles.storage.StaticFilesStorage'
89 'django.contrib.staticfiles.storage.StaticFilesStorage'
90 else:
90 else:
91 STATICFILES_STORAGE = \
91 STATICFILES_STORAGE = \
92 'django.contrib.staticfiles.storage.CachedStaticFilesStorage'
92 'django.contrib.staticfiles.storage.CachedStaticFilesStorage'
93
93
94 # Make this unique, and don't share it with anybody.
94 # Make this unique, and don't share it with anybody.
95 SECRET_KEY = '@1rc$o(7=tt#kd+4s$u6wchm**z^)4x90)7f6z(i&55@o11*8o'
95 SECRET_KEY = '@1rc$o(7=tt#kd+4s$u6wchm**z^)4x90)7f6z(i&55@o11*8o'
96
96
97 # List of callables that know how to import templates from various sources.
97 # List of callables that know how to import templates from various sources.
98 TEMPLATE_LOADERS = (
98 TEMPLATE_LOADERS = (
99 'django.template.loaders.filesystem.Loader',
99 'django.template.loaders.filesystem.Loader',
100 'django.template.loaders.app_directories.Loader',
100 'django.template.loaders.app_directories.Loader',
101 )
101 )
102
102
103 TEMPLATE_CONTEXT_PROCESSORS = (
103 TEMPLATE_CONTEXT_PROCESSORS = (
104 'django.core.context_processors.media',
104 'django.core.context_processors.media',
105 'django.core.context_processors.static',
105 'django.core.context_processors.static',
106 'django.core.context_processors.request',
106 'django.core.context_processors.request',
107 'django.contrib.auth.context_processors.auth',
107 'django.contrib.auth.context_processors.auth',
108 )
108 )
109
109
110 MIDDLEWARE_CLASSES = (
110 MIDDLEWARE_CLASSES = (
111 'django.contrib.sessions.middleware.SessionMiddleware',
111 'django.contrib.sessions.middleware.SessionMiddleware',
112 'django.middleware.locale.LocaleMiddleware',
112 'django.middleware.locale.LocaleMiddleware',
113 'django.middleware.common.CommonMiddleware',
113 'django.middleware.common.CommonMiddleware',
114 'django.middleware.transaction.TransactionMiddleware',
115 'django.contrib.auth.middleware.AuthenticationMiddleware',
114 'django.contrib.auth.middleware.AuthenticationMiddleware',
116 'django.contrib.messages.middleware.MessageMiddleware',
115 'django.contrib.messages.middleware.MessageMiddleware',
117 'boards.middlewares.BanMiddleware',
116 'boards.middlewares.BanMiddleware',
118 )
117 )
119
118
120 ROOT_URLCONF = 'neboard.urls'
119 ROOT_URLCONF = 'neboard.urls'
121
120
122 # Python dotted path to the WSGI application used by Django's runserver.
121 # Python dotted path to the WSGI application used by Django's runserver.
123 WSGI_APPLICATION = 'neboard.wsgi.application'
122 WSGI_APPLICATION = 'neboard.wsgi.application'
124
123
125 TEMPLATE_DIRS = (
124 TEMPLATE_DIRS = (
126 # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
125 # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
127 # Always use forward slashes, even on Windows.
126 # Always use forward slashes, even on Windows.
128 # Don't forget to use absolute paths, not relative paths.
127 # Don't forget to use absolute paths, not relative paths.
129 'templates',
128 'templates',
130 )
129 )
131
130
132 INSTALLED_APPS = (
131 INSTALLED_APPS = (
133 'django.contrib.auth',
132 'django.contrib.auth',
134 'django.contrib.contenttypes',
133 'django.contrib.contenttypes',
135 'django.contrib.sessions',
134 'django.contrib.sessions',
136 # 'django.contrib.sites',
135 # 'django.contrib.sites',
137 'django.contrib.messages',
136 'django.contrib.messages',
138 'django.contrib.staticfiles',
137 'django.contrib.staticfiles',
139 # Uncomment the next line to enable the admin:
138 # Uncomment the next line to enable the admin:
140 'django.contrib.admin',
139 'django.contrib.admin',
141 # Uncomment the next line to enable admin documentation:
140 # Uncomment the next line to enable admin documentation:
142 # 'django.contrib.admindocs',
141 # 'django.contrib.admindocs',
143 'django.contrib.markup',
142 'django.contrib.markup',
144 'django.contrib.humanize',
143 'django.contrib.humanize',
145 'django_cleanup',
144 'django_cleanup',
146 'boards',
145 'boards',
147 'captcha',
146 'captcha',
148 'south',
147 'south',
149 'debug_toolbar',
148 'debug_toolbar',
150 )
149 )
151
150
152 DEBUG_TOOLBAR_PANELS = (
151 DEBUG_TOOLBAR_PANELS = (
153 'debug_toolbar.panels.version.VersionDebugPanel',
152 'debug_toolbar.panels.version.VersionDebugPanel',
154 'debug_toolbar.panels.timer.TimerDebugPanel',
153 'debug_toolbar.panels.timer.TimerDebugPanel',
155 'debug_toolbar.panels.settings_vars.SettingsVarsDebugPanel',
154 'debug_toolbar.panels.settings_vars.SettingsVarsDebugPanel',
156 'debug_toolbar.panels.headers.HeaderDebugPanel',
155 'debug_toolbar.panels.headers.HeaderDebugPanel',
157 'debug_toolbar.panels.request_vars.RequestVarsDebugPanel',
156 'debug_toolbar.panels.request_vars.RequestVarsDebugPanel',
158 'debug_toolbar.panels.template.TemplateDebugPanel',
157 'debug_toolbar.panels.template.TemplateDebugPanel',
159 'debug_toolbar.panels.sql.SQLDebugPanel',
158 'debug_toolbar.panels.sql.SQLDebugPanel',
160 'debug_toolbar.panels.signals.SignalDebugPanel',
159 'debug_toolbar.panels.signals.SignalDebugPanel',
161 'debug_toolbar.panels.logger.LoggingPanel',
160 'debug_toolbar.panels.logger.LoggingPanel',
162 )
161 )
163
162
164 # TODO: NEED DESIGN FIXES
163 # TODO: NEED DESIGN FIXES
165 CAPTCHA_OUTPUT_FORMAT = (u' %(hidden_field)s '
164 CAPTCHA_OUTPUT_FORMAT = (u' %(hidden_field)s '
166 u'<div class="form-label">%(image)s</div>'
165 u'<div class="form-label">%(image)s</div>'
167 u'<div class="form-text">%(text_field)s</div>')
166 u'<div class="form-text">%(text_field)s</div>')
168
167
169 # A sample logging configuration. The only tangible logging
168 # A sample logging configuration. The only tangible logging
170 # performed by this configuration is to send an email to
169 # performed by this configuration is to send an email to
171 # the site admins on every HTTP 500 error when DEBUG=False.
170 # the site admins on every HTTP 500 error when DEBUG=False.
172 # See http://docs.djangoproject.com/en/dev/topics/logging for
171 # See http://docs.djangoproject.com/en/dev/topics/logging for
173 # more details on how to customize your logging configuration.
172 # more details on how to customize your logging configuration.
174 LOGGING = {
173 LOGGING = {
175 'version': 1,
174 'version': 1,
176 'disable_existing_loggers': False,
175 'disable_existing_loggers': False,
177 'filters': {
176 'filters': {
178 'require_debug_false': {
177 'require_debug_false': {
179 '()': 'django.utils.log.RequireDebugFalse'
178 '()': 'django.utils.log.RequireDebugFalse'
180 }
179 }
181 },
180 },
182 'handlers': {
181 'handlers': {
183 'mail_admins': {
182 'mail_admins': {
184 'level': 'ERROR',
183 'level': 'ERROR',
185 'filters': ['require_debug_false'],
184 'filters': ['require_debug_false'],
186 'class': 'django.utils.log.AdminEmailHandler'
185 'class': 'django.utils.log.AdminEmailHandler'
187 }
186 }
188 },
187 },
189 'loggers': {
188 'loggers': {
190 'django.request': {
189 'django.request': {
191 'handlers': ['mail_admins'],
190 'handlers': ['mail_admins'],
192 'level': 'ERROR',
191 'level': 'ERROR',
193 'propagate': True,
192 'propagate': True,
194 },
193 },
195 }
194 }
196 }
195 }
197
196
198 MARKUP_FIELD_TYPES = (
197 MARKUP_FIELD_TYPES = (
199 ('markdown', markdown_extended),
198 ('markdown', markdown_extended),
200 )
199 )
201 # Custom imageboard settings
200 # Custom imageboard settings
202 # TODO These should me moved to
201 # TODO These should me moved to
203 MAX_POSTS_PER_THREAD = 10 # Thread bumplimit
202 MAX_POSTS_PER_THREAD = 10 # Thread bumplimit
204 MAX_THREAD_COUNT = 500 # Old threads will be deleted to preserve this count
203 MAX_THREAD_COUNT = 500 # Old threads will be deleted to preserve this count
205 THREADS_PER_PAGE = 10
204 THREADS_PER_PAGE = 10
206 SITE_NAME = 'Neboard'
205 SITE_NAME = 'Neboard'
207
206
208 THEMES = [
207 THEMES = [
209 ('md', 'Mystic Dark'),
208 ('md', 'Mystic Dark'),
210 ('md_centered', 'Mystic Dark (centered)'),
209 ('md_centered', 'Mystic Dark (centered)'),
211 ('sw', 'Snow White'),
210 ('sw', 'Snow White'),
212 ('pg', 'Photon Gray'),
211 ('pg', 'Photon Gray'),
213 ]
212 ]
214
213
215 DEFAULT_THEME = 'md'
214 DEFAULT_THEME = 'md'
216
215
217 POPULAR_TAGS = 10
216 POPULAR_TAGS = 10
218 LAST_REPLIES_COUNT = 3
217 LAST_REPLIES_COUNT = 3
219
218
220 ENABLE_CAPTCHA = False
219 ENABLE_CAPTCHA = False
221 # if user tries to post before CAPTCHA_DEFAULT_SAFE_TIME. Captcha will be shown
220 # if user tries to post before CAPTCHA_DEFAULT_SAFE_TIME. Captcha will be shown
222 CAPTCHA_DEFAULT_SAFE_TIME = 30 # seconds
221 CAPTCHA_DEFAULT_SAFE_TIME = 30 # seconds
223 POSTING_DELAY = 30 # seconds
222 POSTING_DELAY = 30 # seconds
224
223
225
224
226 def custom_show_toolbar(request):
225 def custom_show_toolbar(request):
227 return DEBUG
226 return DEBUG
228
227
229 DEBUG_TOOLBAR_CONFIG = {
228 DEBUG_TOOLBAR_CONFIG = {
230 'INTERCEPT_REDIRECTS': False,
229 'INTERCEPT_REDIRECTS': False,
231 'SHOW_TOOLBAR_CALLBACK': custom_show_toolbar,
230 'SHOW_TOOLBAR_CALLBACK': custom_show_toolbar,
232 'HIDE_DJANGO_SQL': False,
231 'HIDE_DJANGO_SQL': False,
233 'ENABLE_STACKTRACES': True,
232 'ENABLE_STACKTRACES': True,
234 }
233 }
235
234
236 # Debug mode middlewares
235 # Debug mode middlewares
237 if DEBUG:
236 if DEBUG:
238 MIDDLEWARE_CLASSES += (
237 MIDDLEWARE_CLASSES += (
239 'boards.profiler.ProfilerMiddleware',
238 'boards.profiler.ProfilerMiddleware',
240 'debug_toolbar.middleware.DebugToolbarMiddleware',
239 'debug_toolbar.middleware.DebugToolbarMiddleware',
241 )
240 )
General Comments 0
You need to be logged in to leave comments. Login now