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