##// END OF EJS Templates
Fixed new user creation. Fixed some posting tests.
neko259 -
r202:c95e536c default
parent child Browse files
Show More
@@ -1,333 +1,330 b''
1 1 import os
2 2 from random import random
3 3 import re
4 4 import time
5 5 import math
6 6
7 7 from django.db import models
8 8 from django.db.models import Count
9 9 from django.http import Http404
10 10 from django.utils import timezone
11 11 from markupfield.fields import MarkupField
12 12
13 13 from neboard import settings
14 14 import thumbs
15 15
16 16 IMAGE_THUMB_SIZE = (200, 150)
17 17
18 18 TITLE_MAX_LENGTH = 50
19 19
20 20 DEFAULT_MARKUP_TYPE = 'markdown'
21 21
22 22 NO_PARENT = -1
23 23 NO_IP = '0.0.0.0'
24 24 UNKNOWN_UA = ''
25 25 ALL_PAGES = -1
26 26 OPENING_POST_POPULARITY_WEIGHT = 2
27 27 IMAGES_DIRECTORY = 'images/'
28 28 FILE_EXTENSION_DELIMITER = '.'
29 29
30 30 RANK_ADMIN = 0
31 31 RANK_MODERATOR = 10
32 32 RANK_USER = 100
33 33
34 34
35 35 class PostManager(models.Manager):
36 36
37 37 def create_post(self, title, text, image=None, thread=None,
38 38 ip=NO_IP, tags=None, user=None):
39 39 post = self.create(title=title,
40 40 text=text,
41 41 pub_time=timezone.now(),
42 42 thread=thread,
43 43 image=image,
44 44 poster_ip=ip,
45 45 poster_user_agent=UNKNOWN_UA,
46 46 last_edit_time=timezone.now(),
47 47 bump_time=timezone.now(),
48 48 user=user)
49 49
50 50 if tags:
51 51 map(post.tags.add, tags)
52 52 for tag in tags:
53 53 tag.threads.add(post)
54 54
55 55 if thread:
56 56 thread.replies.add(post)
57 57 thread.bump()
58 58 thread.last_edit_time = timezone.now()
59 59 thread.save()
60 60 else:
61 61 self._delete_old_threads()
62 62
63 63 return post
64 64
65 65 def delete_post(self, post):
66 66 if post.replies.count() > 0:
67 67 map(self.delete_post, post.replies.all())
68 68 post.delete()
69 69
70 70 def delete_posts_by_ip(self, ip):
71 71 posts = self.filter(poster_ip=ip)
72 72 map(self.delete_post, posts)
73 73
74 74 def get_threads(self, tag=None, page=ALL_PAGES,
75 75 order_by='-bump_time'):
76 76 if tag:
77 77 threads = tag.threads
78 78
79 # TODO This needs to be uncommented when 'all tags' view won't
80 # use this method to get threads for tag
81
82 # if threads.count() == 0:
83 # raise Http404
79 if threads.count() == 0:
80 raise Http404
84 81 else:
85 82 threads = self.filter(thread=None)
86 83
87 84 threads = threads.order_by(order_by)
88 85
89 86 if page != ALL_PAGES:
90 87 thread_count = threads.count()
91 88
92 89 if page < self.get_thread_page_count(tag=tag):
93 90 start_thread = page * settings.THREADS_PER_PAGE
94 91 end_thread = min(start_thread + settings.THREADS_PER_PAGE,
95 92 thread_count)
96 93 threads = threads[start_thread:end_thread]
97 94
98 95 return threads
99 96
100 97 def get_thread(self, opening_post_id):
101 98 try:
102 99 opening_post = self.get(id=opening_post_id, thread=None)
103 100 except Post.DoesNotExist:
104 101 raise Http404
105 102
106 103 if opening_post.replies:
107 104 thread = [opening_post]
108 105 thread.extend(opening_post.replies.all())
109 106
110 107 return thread
111 108
112 109 def exists(self, post_id):
113 110 posts = self.filter(id=post_id)
114 111
115 112 return posts.count() > 0
116 113
117 114 def get_thread_page_count(self, tag=None):
118 115 if tag:
119 116 threads = self.filter(thread=None, tags=tag)
120 117 else:
121 118 threads = self.filter(thread=None)
122 119
123 120 return int(math.ceil(threads.count() / float(
124 121 settings.THREADS_PER_PAGE)))
125 122
126 123 def _delete_old_threads(self):
127 124 """
128 125 Preserves maximum thread count. If there are too many threads,
129 126 delete the old ones.
130 127 """
131 128
132 129 # TODO Move old threads to the archive instead of deleting them.
133 130 # Maybe make some 'old' field in the model to indicate the thread
134 131 # must not be shown and be able for replying.
135 132
136 133 threads = self.get_threads()
137 134 thread_count = len(threads)
138 135
139 136 if thread_count > settings.MAX_THREAD_COUNT:
140 137 num_threads_to_delete = thread_count - settings.MAX_THREAD_COUNT
141 138 old_threads = threads[thread_count - num_threads_to_delete:]
142 139
143 140 map(self.delete_post, old_threads)
144 141
145 142
146 143 class TagManager(models.Manager):
147 144
148 145 def get_not_empty_tags(self):
149 146 tags = self.annotate(Count('threads')) \
150 147 .filter(threads__count__gt=0).order_by('name')
151 148
152 149 return tags
153 150
154 151
155 152 class Tag(models.Model):
156 153 """
157 154 A tag is a text node assigned to the post. The tag serves as a board
158 155 section. There can be multiple tags for each message
159 156 """
160 157
161 158 objects = TagManager()
162 159
163 160 name = models.CharField(max_length=100)
164 161 threads = models.ManyToManyField('Post', null=True,
165 162 blank=True, related_name='tag+')
166 163
167 164 def __unicode__(self):
168 165 return self.name
169 166
170 167 def is_empty(self):
171 168 return self.get_post_count() == 0
172 169
173 170 def get_post_count(self):
174 171 return self.threads.count()
175 172
176 173 def get_popularity(self):
177 174 posts_with_tag = Post.objects.get_threads(tag=self)
178 175 reply_count = 0
179 176 for post in posts_with_tag:
180 177 reply_count += post.get_reply_count()
181 178 reply_count += OPENING_POST_POPULARITY_WEIGHT
182 179
183 180 return reply_count
184 181
185 182
186 183 class Post(models.Model):
187 184 """A post is a message."""
188 185
189 186 objects = PostManager()
190 187
191 188 def _update_image_filename(self, filename):
192 189 """Get unique image filename"""
193 190
194 191 path = IMAGES_DIRECTORY
195 192 new_name = str(int(time.mktime(time.gmtime())))
196 193 new_name += str(int(random() * 1000))
197 194 new_name += FILE_EXTENSION_DELIMITER
198 195 new_name += filename.split(FILE_EXTENSION_DELIMITER)[-1:][0]
199 196
200 197 return os.path.join(path, new_name)
201 198
202 199 title = models.CharField(max_length=TITLE_MAX_LENGTH)
203 200 pub_time = models.DateTimeField()
204 201 text = MarkupField(default_markup_type=DEFAULT_MARKUP_TYPE,
205 202 escape_html=False)
206 203
207 204 image_width = models.IntegerField(default=0)
208 205 image_height = models.IntegerField(default=0)
209 206
210 207 image = thumbs.ImageWithThumbsField(upload_to=_update_image_filename,
211 208 blank=True, sizes=(IMAGE_THUMB_SIZE,),
212 209 width_field='image_width',
213 210 height_field='image_height')
214 211
215 212 poster_ip = models.GenericIPAddressField()
216 213 poster_user_agent = models.TextField()
217 214
218 215 thread = models.ForeignKey('Post', null=True, default=None)
219 216 tags = models.ManyToManyField(Tag)
220 217 last_edit_time = models.DateTimeField()
221 218 bump_time = models.DateTimeField()
222 219 user = models.ForeignKey('User', null=True, default=None)
223 220
224 221 replies = models.ManyToManyField('Post', symmetrical=False, null=True,
225 222 blank=True, related_name='re+')
226 223
227 224 def __unicode__(self):
228 225 return '#' + str(self.id) + ' ' + self.title + ' (' + \
229 226 self.text.raw[:50] + ')'
230 227
231 228 def get_title(self):
232 229 title = self.title
233 230 if len(title) == 0:
234 231 title = self.text.raw[:20]
235 232
236 233 return title
237 234
238 235 def get_reply_count(self):
239 236 return self.replies.count()
240 237
241 238 def get_images_count(self):
242 239 images_count = 1 if self.image else 0
243 240 images_count += self.replies.filter(image_width__gt=0).count()
244 241
245 242 return images_count
246 243
247 244 def can_bump(self):
248 245 """Check if the thread can be bumped by replying"""
249 246
250 247 post_count = self.get_reply_count() + 1
251 248
252 249 return post_count <= settings.MAX_POSTS_PER_THREAD
253 250
254 251 def bump(self):
255 252 """Bump (move to up) thread"""
256 253
257 254 if self.can_bump():
258 255 self.bump_time = timezone.now()
259 256
260 257 def get_last_replies(self):
261 258 if settings.LAST_REPLIES_COUNT > 0:
262 259 reply_count = self.get_reply_count()
263 260
264 261 if reply_count > 0:
265 262 reply_count_to_show = min(settings.LAST_REPLIES_COUNT,
266 263 reply_count)
267 264 last_replies = self.replies.all()[reply_count -
268 265 reply_count_to_show:]
269 266
270 267 return last_replies
271 268
272 269
273 270 class User(models.Model):
274 271
275 272 user_id = models.CharField(max_length=50)
276 273 rank = models.IntegerField()
277 274
278 275 registration_time = models.DateTimeField()
279 276
280 277 fav_tags = models.ManyToManyField(Tag, null=True, blank=True)
281 278 fav_threads = models.ManyToManyField(Post, related_name='+', null=True,
282 279 blank=True)
283 280
284 281 def save_setting(self, name, value):
285 282 setting, created = Setting.objects.get_or_create(name=name, user=self)
286 283 setting.value = value
287 284 setting.save()
288 285
289 286 return setting
290 287
291 288 def get_setting(self, name):
292 289 if Setting.objects.filter(name=name, user=self).exists():
293 290 setting = Setting.objects.get(name=name, user=self)
294 291 setting_value = setting.value
295 292 else:
296 293 setting_value = None
297 294
298 295 return setting_value
299 296
300 297 def is_moderator(self):
301 298 return RANK_MODERATOR >= self.rank
302 299
303 300 def get_sorted_fav_tags(self):
304 301 tags = self.fav_tags.annotate(Count('threads'))\
305 302 .filter(threads__count__gt=0).order_by('name')
306 303
307 304 return tags
308 305
309 306 def get_post_count(self):
310 307 return Post.objects.filter(user=self).count()
311 308
312 309 def __unicode__(self):
313 310 return self.user_id + '(' + str(self.rank) + ')'
314 311
315 312 def get_last_access_time(self):
316 313 posts = Post.objects.filter(user=self)
317 314 if posts.count() > 0:
318 315 return posts.latest('pub_time').pub_time
319 316
320 317
321 318 class Setting(models.Model):
322 319
323 320 name = models.CharField(max_length=50)
324 321 value = models.CharField(max_length=50)
325 322 user = models.ForeignKey(User)
326 323
327 324
328 325 class Ban(models.Model):
329 326
330 327 ip = models.GenericIPAddressField()
331 328
332 329 def __unicode__(self):
333 330 return self.ip
@@ -1,175 +1,175 b''
1 1 # coding=utf-8
2 2 from django.utils.unittest import TestCase
3 3 from django.test.client import Client
4 4 import time
5 5
6 6 import boards
7 7
8 8 from boards.models import Post, Tag
9 9 from neboard import settings
10 10
11 11 TEST_TEXT = 'test text'
12 12
13 13 NEW_THREAD_PAGE = '/'
14 14 THREAD_PAGE_ONE = '/thread/1/'
15 15 THREAD_PAGE = '/thread/'
16 16 TAG_PAGE = '/tag/'
17 17 HTTP_CODE_REDIRECT = 302
18 18 HTTP_CODE_OK = 200
19 19 HTTP_CODE_NOT_FOUND = 404
20 20
21 21
22 22 class BoardTests(TestCase):
23 23 def _create_post(self):
24 24 return Post.objects.create_post(title='title',
25 25 text='text')
26 26
27 27 def test_post_add(self):
28 28 post = self._create_post()
29 29
30 30 self.assertIsNotNone(post)
31 self.assertEqual(boards.models.NO_PARENT, post.parent)
31 self.assertIsNone(post.thread, 'Opening post has a thread')
32 32
33 33 def test_delete_post(self):
34 34 post = self._create_post()
35 35 post_id = post.id
36 36
37 37 Post.objects.delete_post(post)
38 38
39 39 self.assertFalse(Post.objects.exists(post_id))
40 40
41 41 def test_delete_posts_by_ip(self):
42 42 post = self._create_post()
43 43 post_id = post.id
44 44
45 45 Post.objects.delete_posts_by_ip('0.0.0.0')
46 46
47 47 self.assertFalse(Post.objects.exists(post_id))
48 48
49 49 # Authentication tests
50 50
51 51 def test_get_thread(self):
52 52 opening_post = self._create_post()
53 53
54 54 for i in range(0, 2):
55 Post.objects.create_post('title', 'text',thread=opening_post)
55 Post.objects.create_post('title', 'text', thread=opening_post)
56 56
57 57 thread = Post.objects.get_thread(opening_post.id)
58 58
59 59 self.assertEqual(3, len(thread))
60 60
61 61 def test_create_post_with_tag(self):
62 62 tag = Tag.objects.create(name='test_tag')
63 63 post = Post.objects.create_post(title='title', text='text', tags=[tag])
64 64 self.assertIsNotNone(post)
65 65
66 66 def test_thread_max_count(self):
67 67 for i in range(settings.MAX_THREAD_COUNT + 1):
68 68 self._create_post()
69 69
70 70 self.assertEqual(settings.MAX_THREAD_COUNT,
71 71 len(Post.objects.get_threads()))
72 72
73 73 def test_pages(self):
74 74 """Test that the thread list is properly split into pages"""
75 75
76 76 for i in range(settings.MAX_THREAD_COUNT):
77 77 self._create_post()
78 78
79 79 all_threads = Post.objects.get_threads()
80 80
81 81 posts_in_second_page = Post.objects.get_threads(page=1)
82 82 first_post = posts_in_second_page[0]
83 83
84 84 self.assertEqual(all_threads[settings.THREADS_PER_PAGE].id,
85 85 first_post.id)
86 86
87 87 def test_post_validation(self):
88 88 """Test the validation of the post form"""
89 89
90 90 # Disable captcha for the test
91 91 captcha_enabled = settings.ENABLE_CAPTCHA
92 92 settings.ENABLE_CAPTCHA = False
93 93
94 94 Post.objects.all().delete()
95 95
96 96 client = Client()
97 97
98 98 valid_tags = u'tag1 tag_2 Ρ‚Π΅Π³_3'
99 99 invalid_tags = u'$%_356 ---'
100 100
101 101 response = client.post(NEW_THREAD_PAGE, {'title': 'test title',
102 102 'text': TEST_TEXT,
103 103 'tags': valid_tags})
104 104 self.assertEqual(response.status_code, HTTP_CODE_REDIRECT,
105 105 msg='Posting new message failed: got code ' +
106 106 str(response.status_code))
107 107
108 108 self.assertEqual(1, Post.objects.count(),
109 109 msg='No posts were created')
110 110
111 111 client.post(NEW_THREAD_PAGE, {'text': TEST_TEXT,
112 112 'tags': invalid_tags})
113 113 self.assertEqual(1, Post.objects.count(), msg='The validation passed '
114 114 'where it should fail')
115 115
116 116 # Change posting delay so we don't have to wait for 30 seconds or more
117 117 old_posting_delay = settings.POSTING_DELAY
118 118 # Wait fot the posting delay or we won't be able to post
119 119 settings.POSTING_DELAY = 1
120 120 time.sleep(settings.POSTING_DELAY + 1)
121 121 response = client.post(THREAD_PAGE_ONE, {'text': TEST_TEXT,
122 122 'tags': valid_tags})
123 123 self.assertEqual(HTTP_CODE_REDIRECT, response.status_code,
124 124 msg=u'Posting new message failed: got code ' +
125 125 str(response.status_code))
126 126 # Restore posting delay
127 127 settings.POSTING_DELAY = old_posting_delay
128 128
129 129 self.assertEqual(2, Post.objects.count(),
130 130 msg=u'No posts were created')
131 131
132 132 # Restore captcha setting
133 133 settings.ENABLE_CAPTCHA = captcha_enabled
134 134
135 135 def test_404(self):
136 136 """Test receiving error 404 when opening a non-existent page"""
137 137
138 138 Post.objects.all().delete()
139 139 Tag.objects.all().delete()
140 140
141 141 tag_name = u'test_tag'
142 142 tags, = [Tag.objects.get_or_create(name=tag_name)]
143 143 client = Client()
144 144
145 145 Post.objects.create_post('title', TEST_TEXT, tags=tags)
146 146
147 147 existing_post_id = Post.objects.all()[0].id
148 148 response_existing = client.get(THREAD_PAGE + str(existing_post_id) +
149 149 '/')
150 150 self.assertEqual(HTTP_CODE_OK, response_existing.status_code,
151 151 u'Cannot open existing thread')
152 152
153 153 response_not_existing = client.get(THREAD_PAGE + str(
154 154 existing_post_id + 1) + '/')
155 155 self.assertEqual('boards/404.html',
156 156 response_not_existing.templates[0].name,
157 157 u'Not existing thread is opened')
158 158
159 159 response_existing = client.get(TAG_PAGE + tag_name + '/')
160 160 self.assertEqual(HTTP_CODE_OK,
161 161 response_existing.status_code,
162 162 u'Cannot open existing tag')
163 163
164 164 response_not_existing = client.get(TAG_PAGE + u'not_tag' + '/')
165 165 self.assertEqual('boards/404.html',
166 166 response_not_existing.templates[0].name,
167 167 u'Not existing tag is opened')
168 168
169 169 reply_id = Post.objects.create_post('', TEST_TEXT,
170 170 thread=Post.objects.all()[0])
171 171 response_not_existing = client.get(THREAD_PAGE + str(
172 172 reply_id) + '/')
173 173 self.assertEqual('boards/404.html',
174 174 response_not_existing.templates[0].name,
175 175 u'Reply is opened as a thread')
@@ -1,355 +1,354 b''
1 1 import hashlib
2 2 import string
3 3 from django.core.urlresolvers import reverse
4 4 from django.http import HttpResponseRedirect
5 5 from django.template import RequestContext
6 6 from django.shortcuts import render, redirect, get_object_or_404
7 7 from django.utils import timezone
8 8
9 9 from boards import forms
10 10 import boards
11 11 from boards import utils
12 12 from boards.forms import ThreadForm, PostForm, SettingsForm, PlainErrorList, \
13 13 ThreadCaptchaForm, PostCaptchaForm, LoginForm
14 14
15 15 from boards.models import Post, Tag, Ban, User, RANK_USER, NO_PARENT
16 16 from boards import authors
17 17 import neboard
18 18
19 19
20 20 def index(request, page=0):
21 21 context = _init_default_context(request)
22 22
23 23 if utils.need_include_captcha(request):
24 24 threadFormClass = ThreadCaptchaForm
25 25 kwargs = {'request': request}
26 26 else:
27 27 threadFormClass = ThreadForm
28 28 kwargs = {}
29 29
30 30 if request.method == 'POST':
31 31 form = threadFormClass(request.POST, request.FILES,
32 32 error_class=PlainErrorList, **kwargs)
33 33 form.session = request.session
34 34
35 35 if form.is_valid():
36 36 return _new_post(request, form)
37 37 else:
38 38 form = threadFormClass(error_class=PlainErrorList, **kwargs)
39 39
40 40 threads = []
41 41 for thread in Post.objects.get_threads(page=int(page)):
42 42 threads.append({'thread': thread,
43 43 'bumpable': thread.can_bump()})
44 44
45 45 context['threads'] = None if len(threads) == 0 else threads
46 46 context['form'] = form
47 47 context['pages'] = range(Post.objects.get_thread_page_count())
48 48
49 49 return render(request, 'boards/posting_general.html',
50 50 context)
51 51
52 52
53 53 def _new_post(request, form, thread_id=boards.models.NO_PARENT):
54 54 """Add a new post (in thread or as a reply)."""
55 55
56 56 ip = _get_client_ip(request)
57 57 is_banned = Ban.objects.filter(ip=ip).count() > 0
58 58
59 59 if is_banned:
60 60 return redirect(you_are_banned)
61 61
62 62 data = form.cleaned_data
63 63
64 64 title = data['title']
65 65 text = data['text']
66 66
67 67 if 'image' in data.keys():
68 68 image = data['image']
69 69 else:
70 70 image = None
71 71
72 72 tags = []
73 73
74 74 new_thread = thread_id == boards.models.NO_PARENT
75 75 if new_thread:
76 76 tag_strings = data['tags']
77 77
78 78 if tag_strings:
79 79 tag_strings = tag_strings.split(' ')
80 80 for tag_name in tag_strings:
81 81 tag_name = string.lower(tag_name.strip())
82 82 if len(tag_name) > 0:
83 83 tag, created = Tag.objects.get_or_create(name=tag_name)
84 84 tags.append(tag)
85 85
86 86 op = None if thread_id == boards.models.NO_PARENT else \
87 87 get_object_or_404(Post, id=thread_id)
88 88 post = Post.objects.create_post(title=title, text=text, ip=ip,
89 89 thread=op, image=image,
90 90 tags=tags, user=_get_user(request))
91 91
92 92 thread_to_show = (post.id if new_thread else thread_id)
93 93
94 94 if new_thread:
95 95 return redirect(thread, post_id=thread_to_show)
96 96 else:
97 97 return redirect(reverse(thread, kwargs={'post_id': thread_to_show}) +
98 98 '#' + str(post.id))
99 99
100 100
101 101 def tag(request, tag_name, page=0):
102 102 """Get all tag threads (posts without a parent)."""
103 103
104 104 tag = get_object_or_404(Tag, name=tag_name)
105 105 threads = []
106 106 for thread in Post.objects.get_threads(tag=tag, page=int(page)):
107 107 threads.append({'thread': thread,
108 108 'bumpable': thread.can_bump()})
109 109
110 110 if request.method == 'POST':
111 111 form = ThreadForm(request.POST, request.FILES,
112 112 error_class=PlainErrorList)
113 113 if form.is_valid():
114 114 return _new_post(request, form)
115 115 else:
116 116 form = forms.ThreadForm(initial={'tags': tag_name},
117 117 error_class=PlainErrorList)
118 118
119 119 context = _init_default_context(request)
120 120 context['threads'] = None if len(threads) == 0 else threads
121 121 context['tag'] = tag
122 122 context['pages'] = range(Post.objects.get_thread_page_count(tag=tag))
123 123
124 124 context['form'] = form
125 125
126 126 return render(request, 'boards/posting_general.html',
127 127 context)
128 128
129 129
130 130 def thread(request, post_id):
131 131 """Get all thread posts"""
132 132
133 133 if utils.need_include_captcha(request):
134 134 postFormClass = PostCaptchaForm
135 135 kwargs = {'request': request}
136 136 else:
137 137 postFormClass = PostForm
138 138 kwargs = {}
139 139
140 140 if request.method == 'POST':
141 141 form = postFormClass(request.POST, request.FILES,
142 142 error_class=PlainErrorList, **kwargs)
143 143 form.session = request.session
144 144
145 145 if form.is_valid():
146 146 return _new_post(request, form, post_id)
147 147 else:
148 148 form = postFormClass(error_class=PlainErrorList, **kwargs)
149 149
150 150 posts = Post.objects.get_thread(post_id)
151 151
152 152 context = _init_default_context(request)
153 153
154 154 context['posts'] = posts
155 155 context['form'] = form
156 156 context['bumpable'] = posts[0].can_bump()
157 157
158 158 return render(request, 'boards/thread.html', context)
159 159
160 160
161 161 def login(request):
162 162 """Log in with user id"""
163 163
164 164 context = _init_default_context(request)
165 165
166 166 if request.method == 'POST':
167 167 form = LoginForm(request.POST, request.FILES,
168 168 error_class=PlainErrorList)
169 169 if form.is_valid():
170 170 user = User.objects.get(user_id=form.cleaned_data['user_id'])
171 171 request.session['user_id'] = user.id
172 172 return redirect(index)
173 173
174 174 else:
175 175 form = LoginForm()
176 176
177 177 context['form'] = form
178 178
179 179 return render(request, 'boards/login.html', context)
180 180
181 181
182 182 def settings(request):
183 183 """User's settings"""
184 184
185 185 context = _init_default_context(request)
186 186
187 187 if request.method == 'POST':
188 188 form = SettingsForm(request.POST)
189 189 if form.is_valid():
190 190 selected_theme = form.cleaned_data['theme']
191 191
192 192 user = _get_user(request)
193 193 user.save_setting('theme', selected_theme)
194 194
195 195 return redirect(settings)
196 196 else:
197 197 selected_theme = _get_theme(request)
198 198 form = SettingsForm(initial={'theme': selected_theme})
199 199 context['form'] = form
200 200
201 201 return render(request, 'boards/settings.html', context)
202 202
203 203
204 204 def all_tags(request):
205 205 """All tags list"""
206 206
207 207 context = _init_default_context(request)
208 208 context['all_tags'] = Tag.objects.get_not_empty_tags()
209 209
210 210 return render(request, 'boards/tags.html', context)
211 211
212 212
213 213 def jump_to_post(request, post_id):
214 214 """Determine thread in which the requested post is and open it's page"""
215 215
216 216 post = get_object_or_404(Post, id=post_id)
217 217
218 218 if not post.thread:
219 219 return redirect(thread, post_id=post.id)
220 220 else:
221 221 return redirect(reverse(thread, kwargs={'post_id': post.thread.id})
222 222 + '#' + str(post.id))
223 223
224 224
225 225 def authors(request):
226 226 context = _init_default_context(request)
227 227 context['authors'] = boards.authors.authors
228 228
229 229 return render(request, 'boards/authors.html', context)
230 230
231 231
232 232 def delete(request, post_id):
233 233 user = _get_user(request)
234 234 post = get_object_or_404(Post, id=post_id)
235 235
236 236 if user.is_moderator():
237 237 # TODO Show confirmation page before deletion
238 238 Post.objects.delete_post(post)
239 239
240 240 if not post.thread:
241 241 return _redirect_to_next(request)
242 242 else:
243 243 return redirect(thread, post_id=post.thread.id)
244 244
245 245
246 246 def ban(request, post_id):
247 247 user = _get_user(request)
248 248 post = get_object_or_404(Post, id=post_id)
249 249
250 250 if user.is_moderator():
251 251 # TODO Show confirmation page before ban
252 252 Ban.objects.get_or_create(ip=post.poster_ip)
253 253
254 254 return _redirect_to_next(request)
255 255
256 256
257 257 def you_are_banned(request):
258 258 context = _init_default_context(request)
259 259 return render(request, 'boards/staticpages/banned.html', context)
260 260
261 261
262 262 def page_404(request):
263 263 context = _init_default_context(request)
264 264 return render(request, 'boards/404.html', context)
265 265
266 266
267 267 def tag_subscribe(request, tag_name):
268 268 user = _get_user(request)
269 269 tag = get_object_or_404(Tag, name=tag_name)
270 270
271 271 if not tag in user.fav_tags.all():
272 272 user.fav_tags.add(tag)
273 273
274 274 return _redirect_to_next(request)
275 275
276 276
277 277 def tag_unsubscribe(request, tag_name):
278 278 user = _get_user(request)
279 279 tag = get_object_or_404(Tag, name=tag_name)
280 280
281 281 if tag in user.fav_tags.all():
282 282 user.fav_tags.remove(tag)
283 283
284 284 return _redirect_to_next(request)
285 285
286 286
287 287 def static_page(request, name):
288 288 context = _init_default_context(request)
289 289 return render(request, 'boards/staticpages/' + name + '.html', context)
290 290
291 291
292 292 def _get_theme(request, user=None):
293 293 """Get user's CSS theme"""
294 294
295 295 if not user:
296 296 user = _get_user(request)
297 297 theme = user.get_setting('theme')
298 298 if not theme:
299 299 theme = neboard.settings.DEFAULT_THEME
300 300
301 301 return theme
302 302
303 303
304 304 def _get_client_ip(request):
305 305 x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
306 306 if x_forwarded_for:
307 307 ip = x_forwarded_for.split(',')[-1].strip()
308 308 else:
309 309 ip = request.META.get('REMOTE_ADDR')
310 310 return ip
311 311
312 312
313 313 def _init_default_context(request):
314 314 """Create context with default values that are used in most views"""
315 315
316 316 context = RequestContext(request)
317 317
318 318 user = _get_user(request)
319 319 context['user'] = user
320 320 context['tags'] = user.get_sorted_fav_tags()
321 321 context['theme'] = _get_theme(request, user)
322 322 context['moderator'] = user.is_moderator()
323 323
324 324 return context
325 325
326 326
327 327 def _get_user(request):
328 328 """Get current user from the session"""
329 329
330 330 session = request.session
331 331 if not 'user_id' in session:
332 332 request.session.save()
333 333
334 334 md5 = hashlib.md5()
335 335 md5.update(session.session_key)
336 336 new_id = md5.hexdigest()
337 337
338 338 time_now = timezone.now()
339 339 user = User.objects.create(user_id=new_id, rank=RANK_USER,
340 registration_time=time_now,
341 last_access_time=time_now)
340 registration_time=time_now)
342 341
343 342 session['user_id'] = user.id
344 343 else:
345 344 user = User.objects.get(id=session['user_id'])
346 345
347 346 return user
348 347
349 348
350 349 def _redirect_to_next(request):
351 350 if 'next' in request.GET:
352 351 next_page = request.GET['next']
353 352 return HttpResponseRedirect(next_page)
354 353 else:
355 354 return redirect(index)
General Comments 0
You need to be logged in to leave comments. Login now