##// END OF EJS Templates
Optimized threads list.
neko259 -
r163:e0408178 default
parent child Browse files
Show More
@@ -1,326 +1,326 b''
1 import os
1 import os
2 from random import random
2 from random import random
3 import re
3 import re
4 import time
4 import time
5 import math
5 import math
6
6
7 from django.db import models
7 from django.db import models
8 from django.http import Http404
8 from django.http import Http404
9 from django.utils import timezone
9 from django.utils import timezone
10 from markupfield.fields import MarkupField
10 from markupfield.fields import MarkupField
11 from threading import Thread
11 from threading import Thread
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 def create_post(self, title, text, image=None, parent_id=NO_PARENT,
36 def create_post(self, title, text, image=None, parent_id=NO_PARENT,
37 ip=NO_IP, tags=None, user=None):
37 ip=NO_IP, tags=None, user=None):
38 post = self.create(title=title,
38 post = self.create(title=title,
39 text=text,
39 text=text,
40 pub_time=timezone.now(),
40 pub_time=timezone.now(),
41 parent=parent_id,
41 parent=parent_id,
42 image=image,
42 image=image,
43 poster_ip=ip,
43 poster_ip=ip,
44 poster_user_agent=UNKNOWN_UA,
44 poster_user_agent=UNKNOWN_UA,
45 last_edit_time=timezone.now(),
45 last_edit_time=timezone.now(),
46 user=user)
46 user=user)
47
47
48 if tags:
48 if tags:
49 map(post.tags.add, tags)
49 map(post.tags.add, tags)
50
50
51 if parent_id != NO_PARENT:
51 if parent_id != NO_PARENT:
52 self._bump_thread(parent_id)
52 self._bump_thread(parent_id)
53 else:
53 else:
54 self._delete_old_threads()
54 self._delete_old_threads()
55
55
56 return post
56 return post
57
57
58 def delete_post(self, post):
58 def delete_post(self, post):
59 children = self.filter(parent=post.id)
59 children = self.filter(parent=post.id)
60
60
61 map(self.delete_post, children)
61 map(self.delete_post, children)
62 post.delete()
62 post.delete()
63
63
64 def delete_posts_by_ip(self, ip):
64 def delete_posts_by_ip(self, ip):
65 posts = self.filter(poster_ip=ip)
65 posts = self.filter(poster_ip=ip)
66 map(self.delete_post, posts)
66 map(self.delete_post, posts)
67
67
68 def get_threads(self, tag=None, page=ALL_PAGES,
68 def get_threads(self, tag=None, page=ALL_PAGES,
69 order_by='-last_edit_time'):
69 order_by='-last_edit_time'):
70 if tag:
70 if tag:
71 threads = self.filter(parent=NO_PARENT, tags=tag)
71 threads = self.filter(parent=NO_PARENT, tags=tag)
72
72
73 # TODO Throw error 404 if no threads for tag found?
73 # TODO Throw error 404 if no threads for tag found?
74 else:
74 else:
75 threads = self.filter(parent=NO_PARENT)
75 threads = self.filter(parent=NO_PARENT)
76
76
77 threads = threads.order_by(order_by)
77 threads = threads.order_by(order_by)
78
78
79 if page != ALL_PAGES:
79 if page != ALL_PAGES:
80 thread_count = len(threads)
80 thread_count = threads.count()
81
81
82 if page < self.get_thread_page_count(tag=tag):
82 if page < self.get_thread_page_count(tag=tag):
83 start_thread = page * settings.THREADS_PER_PAGE
83 start_thread = page * settings.THREADS_PER_PAGE
84 end_thread = min(start_thread + settings.THREADS_PER_PAGE,
84 end_thread = min(start_thread + settings.THREADS_PER_PAGE,
85 thread_count)
85 thread_count)
86 threads = threads[start_thread:end_thread]
86 threads = threads[start_thread:end_thread]
87
87
88 return threads
88 return threads
89
89
90 def get_thread(self, opening_post_id):
90 def get_thread(self, opening_post_id):
91 try:
91 try:
92 opening_post = self.get(id=opening_post_id, parent=NO_PARENT)
92 opening_post = self.get(id=opening_post_id, parent=NO_PARENT)
93 except Post.DoesNotExist:
93 except Post.DoesNotExist:
94 raise Http404
94 raise Http404
95
95
96 if opening_post.parent == NO_PARENT:
96 if opening_post.parent == NO_PARENT:
97 replies = self.filter(parent=opening_post_id)
97 replies = self.filter(parent=opening_post_id)
98
98
99 thread = [opening_post]
99 thread = [opening_post]
100 thread.extend(replies)
100 thread.extend(replies)
101
101
102 return thread
102 return thread
103
103
104 def exists(self, post_id):
104 def exists(self, post_id):
105 posts = self.filter(id=post_id)
105 posts = self.filter(id=post_id)
106
106
107 return posts.count() > 0
107 return posts.count() > 0
108
108
109 def get_thread_page_count(self, tag=None):
109 def get_thread_page_count(self, tag=None):
110 if tag:
110 if tag:
111 threads = self.filter(parent=NO_PARENT, tags=tag)
111 threads = self.filter(parent=NO_PARENT, tags=tag)
112 else:
112 else:
113 threads = self.filter(parent=NO_PARENT)
113 threads = self.filter(parent=NO_PARENT)
114
114
115 return int(math.ceil(threads.count() / float(
115 return int(math.ceil(threads.count() / float(
116 settings.THREADS_PER_PAGE)))
116 settings.THREADS_PER_PAGE)))
117
117
118 def _delete_old_threads(self):
118 def _delete_old_threads(self):
119 """
119 """
120 Preserves maximum thread count. If there are too many threads,
120 Preserves maximum thread count. If there are too many threads,
121 delete the old ones.
121 delete the old ones.
122 """
122 """
123
123
124 # TODO Move old threads to the archive instead of deleting them.
124 # TODO Move old threads to the archive instead of deleting them.
125 # Maybe make some 'old' field in the model to indicate the thread
125 # Maybe make some 'old' field in the model to indicate the thread
126 # must not be shown and be able for replying.
126 # must not be shown and be able for replying.
127
127
128 threads = self.get_threads()
128 threads = self.get_threads()
129 thread_count = len(threads)
129 thread_count = len(threads)
130
130
131 if thread_count > settings.MAX_THREAD_COUNT:
131 if thread_count > settings.MAX_THREAD_COUNT:
132 num_threads_to_delete = thread_count - settings.MAX_THREAD_COUNT
132 num_threads_to_delete = thread_count - settings.MAX_THREAD_COUNT
133 old_threads = threads[thread_count - num_threads_to_delete:]
133 old_threads = threads[thread_count - num_threads_to_delete:]
134
134
135 map(self.delete_post, old_threads)
135 map(self.delete_post, old_threads)
136
136
137 def _bump_thread(self, thread_id):
137 def _bump_thread(self, thread_id):
138 thread = self.get(id=thread_id)
138 thread = self.get(id=thread_id)
139
139
140 if thread.can_bump():
140 if thread.can_bump():
141 thread.last_edit_time = timezone.now()
141 thread.last_edit_time = timezone.now()
142 thread.save()
142 thread.save()
143
143
144
144
145 class TagManager(models.Manager):
145 class TagManager(models.Manager):
146 def get_not_empty_tags(self):
146 def get_not_empty_tags(self):
147 all_tags = self.all().order_by('name')
147 all_tags = self.all().order_by('name')
148 tags = []
148 tags = []
149 for tag in all_tags:
149 for tag in all_tags:
150 if not tag.is_empty():
150 if not tag.is_empty():
151 tags.append(tag)
151 tags.append(tag)
152
152
153 return tags
153 return tags
154
154
155 def get_popular_tags(self):
155 def get_popular_tags(self):
156 all_tags = self.get_not_empty_tags()
156 all_tags = self.get_not_empty_tags()
157
157
158 sorted_tags = sorted(all_tags, key=lambda tag: tag.get_popularity(),
158 sorted_tags = sorted(all_tags, key=lambda tag: tag.get_popularity(),
159 reverse=True)
159 reverse=True)
160
160
161 return sorted_tags[:settings.POPULAR_TAGS]
161 return sorted_tags[:settings.POPULAR_TAGS]
162
162
163
163
164 class Tag(models.Model):
164 class Tag(models.Model):
165 """
165 """
166 A tag is a text node assigned to the post. The tag serves as a board
166 A tag is a text node assigned to the post. The tag serves as a board
167 section. There can be multiple tags for each message
167 section. There can be multiple tags for each message
168 """
168 """
169
169
170 objects = TagManager()
170 objects = TagManager()
171
171
172 name = models.CharField(max_length=100)
172 name = models.CharField(max_length=100)
173
173
174 def __unicode__(self):
174 def __unicode__(self):
175 return self.name
175 return self.name
176
176
177 def is_empty(self):
177 def is_empty(self):
178 return self.get_post_count() == 0
178 return self.get_post_count() == 0
179
179
180 def get_post_count(self):
180 def get_post_count(self):
181 posts_with_tag = Post.objects.get_threads(tag=self)
181 posts_with_tag = Post.objects.get_threads(tag=self)
182 return posts_with_tag.count()
182 return posts_with_tag.count()
183
183
184 def get_popularity(self):
184 def get_popularity(self):
185 posts_with_tag = Post.objects.get_threads(tag=self)
185 posts_with_tag = Post.objects.get_threads(tag=self)
186 reply_count = 0
186 reply_count = 0
187 for post in posts_with_tag:
187 for post in posts_with_tag:
188 reply_count += post.get_reply_count()
188 reply_count += post.get_reply_count()
189 reply_count += OPENING_POST_POPULARITY_WEIGHT
189 reply_count += OPENING_POST_POPULARITY_WEIGHT
190
190
191 return reply_count
191 return reply_count
192
192
193
193
194 class Post(models.Model):
194 class Post(models.Model):
195 """A post is a message."""
195 """A post is a message."""
196
196
197 objects = PostManager()
197 objects = PostManager()
198
198
199 def _update_image_filename(self, filename):
199 def _update_image_filename(self, filename):
200 """Get unique image filename"""
200 """Get unique image filename"""
201
201
202 path = IMAGES_DIRECTORY
202 path = IMAGES_DIRECTORY
203 new_name = str(int(time.mktime(time.gmtime())))
203 new_name = str(int(time.mktime(time.gmtime())))
204 new_name += str(int(random() * 1000))
204 new_name += str(int(random() * 1000))
205 new_name += FILE_EXTENSION_DELIMITER
205 new_name += FILE_EXTENSION_DELIMITER
206 new_name += filename.split(FILE_EXTENSION_DELIMITER)[-1:][0]
206 new_name += filename.split(FILE_EXTENSION_DELIMITER)[-1:][0]
207
207
208 return os.path.join(path, new_name)
208 return os.path.join(path, new_name)
209
209
210 title = models.CharField(max_length=TITLE_MAX_LENGTH)
210 title = models.CharField(max_length=TITLE_MAX_LENGTH)
211 pub_time = models.DateTimeField()
211 pub_time = models.DateTimeField()
212 text = MarkupField(default_markup_type=DEFAULT_MARKUP_TYPE,
212 text = MarkupField(default_markup_type=DEFAULT_MARKUP_TYPE,
213 escape_html=False)
213 escape_html=False)
214
214
215 image_width = models.IntegerField(default=0)
215 image_width = models.IntegerField(default=0)
216 image_height = models.IntegerField(default=0)
216 image_height = models.IntegerField(default=0)
217
217
218 image = thumbs.ImageWithThumbsField(upload_to=_update_image_filename,
218 image = thumbs.ImageWithThumbsField(upload_to=_update_image_filename,
219 blank=True, sizes=(IMAGE_THUMB_SIZE,),
219 blank=True, sizes=(IMAGE_THUMB_SIZE,),
220 width_field='image_width',
220 width_field='image_width',
221 height_field='image_height')
221 height_field='image_height')
222
222
223 poster_ip = models.GenericIPAddressField()
223 poster_ip = models.GenericIPAddressField()
224 poster_user_agent = models.TextField()
224 poster_user_agent = models.TextField()
225 parent = models.BigIntegerField()
225 parent = models.BigIntegerField()
226 tags = models.ManyToManyField(Tag)
226 tags = models.ManyToManyField(Tag)
227 last_edit_time = models.DateTimeField()
227 last_edit_time = models.DateTimeField()
228 user = models.ForeignKey('User', null=True, default=None)
228 user = models.ForeignKey('User', null=True, default=None)
229
229
230 def __unicode__(self):
230 def __unicode__(self):
231 return '#' + str(self.id) + ' ' + self.title + ' (' + \
231 return '#' + str(self.id) + ' ' + self.title + ' (' + \
232 self.text.raw[:50] + ')'
232 self.text.raw[:50] + ')'
233
233
234 def get_title(self):
234 def get_title(self):
235 title = self.title
235 title = self.title
236 if len(title) == 0:
236 if len(title) == 0:
237 title = self.text.raw[:20]
237 title = self.text.raw[:20]
238
238
239 return title
239 return title
240
240
241 def _get_replies(self):
241 def _get_replies(self):
242 return Post.objects.filter(parent=self.id)
242 return Post.objects.filter(parent=self.id)
243
243
244 def get_reply_count(self):
244 def get_reply_count(self):
245 return self._get_replies().count()
245 return self._get_replies().count()
246
246
247 def get_images_count(self):
247 def get_images_count(self):
248 images_count = 1 if self.image else 0
248 images_count = 1 if self.image else 0
249
249
250 replies = self._get_replies()
250 replies = self._get_replies()
251 for reply in replies:
251 for reply in replies:
252 if reply.image:
252 if reply.image:
253 images_count += 1
253 images_count += 1
254
254
255 return images_count
255 return images_count
256
256
257 def can_bump(self):
257 def can_bump(self):
258 """Check if the thread can be bumped by replying"""
258 """Check if the thread can be bumped by replying"""
259
259
260 replies_count = self.get_reply_count() + 1
260 replies_count = self.get_reply_count() + 1
261
261
262 return replies_count <= settings.MAX_POSTS_PER_THREAD
262 return replies_count <= settings.MAX_POSTS_PER_THREAD
263
263
264 def get_last_replies(self):
264 def get_last_replies(self):
265 if settings.LAST_REPLIES_COUNT > 0:
265 if settings.LAST_REPLIES_COUNT > 0:
266 reply_count = self.get_reply_count()
266 reply_count = self.get_reply_count()
267
267
268 if reply_count > 0:
268 if reply_count > 0:
269 reply_count_to_show = min(settings.LAST_REPLIES_COUNT,
269 reply_count_to_show = min(settings.LAST_REPLIES_COUNT,
270 reply_count)
270 reply_count)
271 last_replies = self._get_replies()[reply_count
271 last_replies = self._get_replies()[reply_count
272 - reply_count_to_show:]
272 - reply_count_to_show:]
273
273
274 return last_replies
274 return last_replies
275
275
276
276
277 class User(models.Model):
277 class User(models.Model):
278
278
279 user_id = models.CharField(max_length=50)
279 user_id = models.CharField(max_length=50)
280 rank = models.IntegerField()
280 rank = models.IntegerField()
281
281
282 registration_time = models.DateTimeField()
282 registration_time = models.DateTimeField()
283 last_access_time = models.DateTimeField()
283 last_access_time = models.DateTimeField()
284
284
285 fav_tags = models.ManyToManyField(Tag, null=True, blank=True)
285 fav_tags = models.ManyToManyField(Tag, null=True, blank=True)
286 fav_threads = models.ManyToManyField(Post, related_name='+', null=True,
286 fav_threads = models.ManyToManyField(Post, related_name='+', null=True,
287 blank=True)
287 blank=True)
288
288
289 def save_setting(self, name, value):
289 def save_setting(self, name, value):
290 setting, created = Setting.objects.get_or_create(name=name, user=self)
290 setting, created = Setting.objects.get_or_create(name=name, user=self)
291 setting.value = value
291 setting.value = value
292 setting.save()
292 setting.save()
293
293
294 return setting
294 return setting
295
295
296 def get_setting(self, name):
296 def get_setting(self, name):
297 if Setting.objects.filter(name=name, user=self).exists():
297 if Setting.objects.filter(name=name, user=self).exists():
298 setting = Setting.objects.get(name=name, user=self)
298 setting = Setting.objects.get(name=name, user=self)
299 setting_value = setting.value
299 setting_value = setting.value
300 else:
300 else:
301 setting_value = None
301 setting_value = None
302
302
303 return setting_value
303 return setting_value
304
304
305 def is_moderator(self):
305 def is_moderator(self):
306 return RANK_MODERATOR >= self.rank
306 return RANK_MODERATOR >= self.rank
307
307
308 def get_sorted_fav_tags(self):
308 def get_sorted_fav_tags(self):
309 return self.fav_tags.order_by('name')
309 return self.fav_tags.order_by('name')
310
310
311 def __unicode__(self):
311 def __unicode__(self):
312 return self.user_id + '(' + str(self.rank) + ')'
312 return self.user_id + '(' + str(self.rank) + ')'
313
313
314
314
315 class Setting(models.Model):
315 class Setting(models.Model):
316
316
317 name = models.CharField(max_length=50)
317 name = models.CharField(max_length=50)
318 value = models.CharField(max_length=50)
318 value = models.CharField(max_length=50)
319 user = models.ForeignKey(User)
319 user = models.ForeignKey(User)
320
320
321
321
322 class Ban(models.Model):
322 class Ban(models.Model):
323 ip = models.GenericIPAddressField()
323 ip = models.GenericIPAddressField()
324
324
325 def __unicode__(self):
325 def __unicode__(self):
326 return self.ip
326 return self.ip
@@ -1,182 +1,182 b''
1 {% extends "boards/base.html" %}
1 {% extends "boards/base.html" %}
2
2
3 {% load i18n %}
3 {% load i18n %}
4 {% load markup %}
4 {% load markup %}
5
5
6 {% block head %}
6 {% block head %}
7 {% if tag %}
7 {% if tag %}
8 <title>Neboard - {{ tag }}</title>
8 <title>Neboard - {{ tag }}</title>
9 {% else %}
9 {% else %}
10 <title>Neboard</title>
10 <title>Neboard</title>
11 {% endif %}
11 {% endif %}
12 {% endblock %}
12 {% endblock %}
13
13
14 {% block content %}
14 {% block content %}
15
15
16 {% if tag %}
16 {% if tag %}
17 <div class="tag_info">
17 <div class="tag_info">
18 <h2>{% trans 'Tag: ' %}{{ tag }}</h2>
18 <h2>{% trans 'Tag: ' %}{{ tag }}</h2>
19 </div>
19 </div>
20 {% endif %}
20 {% endif %}
21
21
22 {% if threads %}
22 {% if threads %}
23 {% for thread in threads %}
23 {% for thread in threads %}
24 <div class="thread">
24 <div class="thread">
25 {% if thread.can_bump %}
25 {% if thread.bumpable %}
26 <div class="post" id="{{thread.id}}">
26 <div class="post" id="{{ thread.thread.id }}">
27 {% else %}
27 {% else %}
28 <div class="post dead_post" id="{{ thread.id }}">
28 <div class="post dead_post" id="{{ thread.thread.id }}">
29 {% endif %}
29 {% endif %}
30 {% if thread.image %}
30 {% if thread.thread.image %}
31 <div class="image">
31 <div class="image">
32 <a class="fancy"
32 <a class="fancy"
33 href="{{ thread.image.url }}"><img
33 href="{{ thread.thread.image.url }}"><img
34 src="{{ thread.image.url_200x150 }}"
34 src="{{ thread.thread.image.url_200x150 }}"
35 alt="{% trans 'Post image' %}"
35 alt="{% trans 'Post image' %}"
36 data-width="{{ thread.image_width }}"
36 data-width="{{ thread.thread.image_width }}"
37 data-height="{{ thread.image_height }}" />
37 data-height="{{ thread.thread.image_height }}" />
38 </a>
38 </a>
39 </div>
39 </div>
40 {% endif %}
40 {% endif %}
41 <div class="message">
41 <div class="message">
42 <div class="post-info">
42 <div class="post-info">
43 <span class="title">{{ thread.title }}</span>
43 <span class="title">{{ thread.thread.title }}</span>
44 <a class="post_id" href="{% url 'thread' thread.id %}"
44 <a class="post_id" href="{% url 'thread' thread.thread.id %}"
45 >(#{{ thread.id }})</a>
45 >(#{{ thread.thread.id }})</a>
46 [{{ thread.pub_time }}]
46 [{{ thread.thread.pub_time }}]
47 [<a class="link" href="{% url 'thread' thread.id %}#form"
47 [<a class="link" href="{% url 'thread' thread.thread.id %}#form"
48 >{% trans "Reply" %}</a>]
48 >{% trans "Reply" %}</a>]
49
49
50 {% if user.is_moderator %}
50 {% if user.is_moderator %}
51 <span class="moderator_info">
51 <span class="moderator_info">
52 [<a href="{% url 'delete' post_id=thread.id %}?next={{ request.path }}"
52 [<a href="{% url 'delete' post_id=thread.thread.id %}?next={{ request.path }}"
53 >{% trans 'Delete' %}</a>]
53 >{% trans 'Delete' %}</a>]
54 ({{ thread.poster_ip }})
54 ({{ thread.thread.poster_ip }})
55 [<a href="{% url 'ban' post_id=thread.id %}?next={{ request.path }}"
55 [<a href="{% url 'ban' post_id=thread.thread.id %}?next={{ request.path }}"
56 >{% trans 'Ban IP' %}</a>]
56 >{% trans 'Ban IP' %}</a>]
57 </span>
57 </span>
58 {% endif %}
58 {% endif %}
59 </div>
59 </div>
60 {% autoescape off %}
60 {% autoescape off %}
61 {{ thread.text.rendered|truncatewords_html:50 }}
61 {{ thread.thread.text.rendered|truncatewords_html:50 }}
62 {% endautoescape %}
62 {% endautoescape %}
63 </div>
63 </div>
64 <div class="metadata">
64 <div class="metadata">
65 {{ thread.get_reply_count }} {% trans 'replies' %},
65 {{ thread.thread.get_reply_count }} {% trans 'replies' %},
66 {{ thread.get_images_count }} {% trans 'images' %}.
66 {{ thread.thread.get_images_count }} {% trans 'images' %}.
67 {% if thread.tags.exists %}
67 {% if thread.tags.exists %}
68 <span class="tags">{% trans 'Tags' %}:
68 <span class="tags">{% trans 'Tags' %}:
69 {% for tag in thread.tags.all %}
69 {% for tag in thread.thread.tags.all %}
70 <a class="tag" href="
70 <a class="tag" href="
71 {% url 'tag' tag_name=tag.name %}">
71 {% url 'tag' tag_name=tag.name %}">
72 {{ tag.name }}</a>
72 {{ tag.name }}</a>
73 {% endfor %}
73 {% endfor %}
74 </span>
74 </span>
75 {% endif %}
75 {% endif %}
76 </div>
76 </div>
77 </div>
77 </div>
78 {% if thread.get_last_replies %}
78 {% if thread.thread.get_last_replies %}
79 <div class="last-replies">
79 <div class="last-replies">
80 {% for post in thread.get_last_replies %}
80 {% for post in thread.thread.get_last_replies %}
81 {% if thread.can_bump %}
81 {% if thread.bumpable %}
82 <div class="post" id="{{ post.id }}">
82 <div class="post" id="{{ post.id }}">
83 {% else %}
83 {% else %}
84 <div class="post dead_post id="{{ post.id }}">
84 <div class="post dead_post" id="{{ post.id }}">
85 {% endif %}
85 {% endif %}
86 {% if post.image %}
86 {% if post.image %}
87 <div class="image">
87 <div class="image">
88 <a class="fancy"
88 <a class="fancy"
89 href="{{ post.image.url }}"><img
89 href="{{ post.image.url }}"><img
90 src=" {{ post.image.url_200x150 }}"
90 src=" {{ post.image.url_200x150 }}"
91 alt="{% trans 'Post image' %}"
91 alt="{% trans 'Post image' %}"
92 data-width="{{ post.image_width }}"
92 data-width="{{ post.image_width }}"
93 data-height="{{ post.image_height }}"/>
93 data-height="{{ post.image_height }}"/>
94 </a>
94 </a>
95 </div>
95 </div>
96 {% endif %}
96 {% endif %}
97 <div class="message">
97 <div class="message">
98 <div class="post-info">
98 <div class="post-info">
99 <span class="title">{{ post.title }}</span>
99 <span class="title">{{ post.title }}</span>
100 <a class="post_id" href="
100 <a class="post_id" href="
101 {% url 'thread' thread.id %}#{{ post.id }}">
101 {% url 'thread' thread.thread.id %}#{{ post.id }}">
102 (#{{ post.id }})</a>
102 (#{{ post.id }})</a>
103 [{{ post.pub_time }}]
103 [{{ post.pub_time }}]
104 </div>
104 </div>
105 {% autoescape off %}
105 {% autoescape off %}
106 {{ post.text.rendered|truncatewords_html:50 }}
106 {{ post.text.rendered|truncatewords_html:50 }}
107 {% endautoescape %}
107 {% endautoescape %}
108 </div>
108 </div>
109 </div>
109 </div>
110 {% endfor %}
110 {% endfor %}
111 </div>
111 </div>
112 {% endif %}
112 {% endif %}
113 </div>
113 </div>
114 {% endfor %}
114 {% endfor %}
115 {% else %}
115 {% else %}
116 <div class="post">
116 <div class="post">
117 {% trans 'No threads exist. Create the first one!' %}</div>
117 {% trans 'No threads exist. Create the first one!' %}</div>
118 {% endif %}
118 {% endif %}
119
119
120 <form enctype="multipart/form-data" method="post">{% csrf_token %}
120 <form enctype="multipart/form-data" method="post">{% csrf_token %}
121 <div class="post-form-w">
121 <div class="post-form-w">
122
122
123 <div class="form-title">{% trans "Create new thread" %}</div>
123 <div class="form-title">{% trans "Create new thread" %}</div>
124 <div class="post-form">
124 <div class="post-form">
125 <div class="form-row">
125 <div class="form-row">
126 <div class="form-label">{% trans 'Title' %}</div>
126 <div class="form-label">{% trans 'Title' %}</div>
127 <div class="form-input">{{ form.title }}</div>
127 <div class="form-input">{{ form.title }}</div>
128 <div class="form-errors">{{ form.title.errors }}</div>
128 <div class="form-errors">{{ form.title.errors }}</div>
129 </div>
129 </div>
130 <div class="form-row">
130 <div class="form-row">
131 <div class="form-label">{% trans 'Text' %}</div>
131 <div class="form-label">{% trans 'Text' %}</div>
132 <div class="form-input">{{ form.text }}</div>
132 <div class="form-input">{{ form.text }}</div>
133 <div class="form-errors">{{ form.text.errors }}</div>
133 <div class="form-errors">{{ form.text.errors }}</div>
134 </div>
134 </div>
135 <div class="form-row">
135 <div class="form-row">
136 <div class="form-label">{% trans 'Image' %}</div>
136 <div class="form-label">{% trans 'Image' %}</div>
137 <div class="form-input">{{ form.image }}</div>
137 <div class="form-input">{{ form.image }}</div>
138 <div class="form-errors">{{ form.image.errors }}</div>
138 <div class="form-errors">{{ form.image.errors }}</div>
139 </div>
139 </div>
140 <div class="form-row">
140 <div class="form-row">
141 <div class="form-label">{% trans 'Tags' %}</div>
141 <div class="form-label">{% trans 'Tags' %}</div>
142 <div class="form-input">{{ form.tags }}</div>
142 <div class="form-input">{{ form.tags }}</div>
143 <div class="form-errors">{{ form.tags.errors }}</div>
143 <div class="form-errors">{{ form.tags.errors }}</div>
144 </div>
144 </div>
145 <div class="form-row">
145 <div class="form-row">
146 {{ form.captcha }}
146 {{ form.captcha }}
147 <div class="form-errors">{{ form.captcha.errors }}</div>
147 <div class="form-errors">{{ form.captcha.errors }}</div>
148 </div>
148 </div>
149 <div class="form-row">
149 <div class="form-row">
150 <div class="form-errors">{{ form.other.errors }}</div>
150 <div class="form-errors">{{ form.other.errors }}</div>
151 </div>
151 </div>
152 </div>
152 </div>
153 <div class="form-submit">
153 <div class="form-submit">
154 <input type="submit" value="{% trans "Post" %}"/></div>
154 <input type="submit" value="{% trans "Post" %}"/></div>
155 <div>
155 <div>
156 {% trans 'Tags must be delimited by spaces. Text or image is required.' %}
156 {% trans 'Tags must be delimited by spaces. Text or image is required.' %}
157 </div>
157 </div>
158 <div><a href="{% url "staticpage" name="help" %}">
158 <div><a href="{% url "staticpage" name="help" %}">
159 {% trans 'Text syntax' %}</a></div>
159 {% trans 'Text syntax' %}</a></div>
160 </div>
160 </div>
161 </form>
161 </form>
162
162
163 {% endblock %}
163 {% endblock %}
164
164
165 {% block metapanel %}
165 {% block metapanel %}
166
166
167 <span class="metapanel">
167 <span class="metapanel">
168 <b><a href="{% url "authors" %}">Neboard</a> 1.1</b>
168 <b><a href="{% url "authors" %}">Neboard</a> 1.1</b>
169 {% trans "Pages:" %}
169 {% trans "Pages:" %}
170 {% for page in pages %}
170 {% for page in pages %}
171 [<a href="
171 [<a href="
172 {% if tag %}
172 {% if tag %}
173 {% url "tag" tag_name=tag page=page %}
173 {% url "tag" tag_name=tag page=page %}
174 {% else %}
174 {% else %}
175 {% url "index" page=page %}
175 {% url "index" page=page %}
176 {% endif %}
176 {% endif %}
177 ">{{ page }}</a>]
177 ">{{ page }}</a>]
178 {% endfor %}
178 {% endfor %}
179 [<a href="rss/">RSS</a>]
179 [<a href="rss/">RSS</a>]
180 </span>
180 </span>
181
181
182 {% endblock %}
182 {% endblock %}
@@ -1,352 +1,355 b''
1 import hashlib
1 import hashlib
2 from django.core.urlresolvers import reverse
2 from django.core.urlresolvers import reverse
3 from django.http import HttpResponseRedirect
3 from django.http import HttpResponseRedirect
4 from django.template import RequestContext
4 from django.template import RequestContext
5 from django.shortcuts import render, redirect, get_object_or_404
5 from django.shortcuts import render, redirect, get_object_or_404
6 from django.utils import timezone
6 from django.utils import timezone
7
7
8 from boards import forms
8 from boards import forms
9 import boards
9 import boards
10 from boards import utils
10 from boards import utils
11 from boards.forms import ThreadForm, PostForm, SettingsForm, PlainErrorList, \
11 from boards.forms import ThreadForm, PostForm, SettingsForm, PlainErrorList, \
12 ThreadCaptchaForm, PostCaptchaForm, LoginForm
12 ThreadCaptchaForm, PostCaptchaForm, LoginForm
13
13
14 from boards.models import Post, Tag, Ban, User, RANK_USER, NO_PARENT
14 from boards.models import Post, Tag, Ban, User, RANK_USER, NO_PARENT
15 from boards import authors
15 from boards import authors
16 import neboard
16 import neboard
17
17
18
18
19 def index(request, page=0):
19 def index(request, page=0):
20 context = _init_default_context(request)
20 context = _init_default_context(request)
21
21
22 if utils.need_include_captcha(request):
22 if utils.need_include_captcha(request):
23 threadFormClass = ThreadCaptchaForm
23 threadFormClass = ThreadCaptchaForm
24 kwargs = {'request': request}
24 kwargs = {'request': request}
25 else:
25 else:
26 threadFormClass = ThreadForm
26 threadFormClass = ThreadForm
27 kwargs = {}
27 kwargs = {}
28
28
29 if request.method == 'POST':
29 if request.method == 'POST':
30 form = threadFormClass(request.POST, request.FILES,
30 form = threadFormClass(request.POST, request.FILES,
31 error_class=PlainErrorList, **kwargs)
31 error_class=PlainErrorList, **kwargs)
32 form.session = request.session
32 form.session = request.session
33
33
34 if form.is_valid():
34 if form.is_valid():
35 return _new_post(request, form)
35 return _new_post(request, form)
36 else:
36 else:
37 form = threadFormClass(error_class=PlainErrorList, **kwargs)
37 form = threadFormClass(error_class=PlainErrorList, **kwargs)
38
38
39 threads = Post.objects.get_threads(page=int(page))
39 threads = []
40 for thread in Post.objects.get_threads(page=int(page)):
41 threads.append({'thread': thread,
42 'bumpable': thread.can_bump()})
40
43
41 context['threads'] = None if len(threads) == 0 else threads
44 context['threads'] = None if len(threads) == 0 else threads
42 context['form'] = form
45 context['form'] = form
43 context['pages'] = range(Post.objects.get_thread_page_count())
46 context['pages'] = range(Post.objects.get_thread_page_count())
44
47
45 return render(request, 'boards/posting_general.html',
48 return render(request, 'boards/posting_general.html',
46 context)
49 context)
47
50
48
51
49 def _new_post(request, form, thread_id=boards.models.NO_PARENT):
52 def _new_post(request, form, thread_id=boards.models.NO_PARENT):
50 """Add a new post (in thread or as a reply)."""
53 """Add a new post (in thread or as a reply)."""
51
54
52 ip = _get_client_ip(request)
55 ip = _get_client_ip(request)
53 is_banned = Ban.objects.filter(ip=ip).count() > 0
56 is_banned = Ban.objects.filter(ip=ip).count() > 0
54
57
55 if is_banned:
58 if is_banned:
56 return redirect(you_are_banned)
59 return redirect(you_are_banned)
57
60
58 data = form.cleaned_data
61 data = form.cleaned_data
59
62
60 title = data['title']
63 title = data['title']
61 text = data['text']
64 text = data['text']
62
65
63 if 'image' in data.keys():
66 if 'image' in data.keys():
64 image = data['image']
67 image = data['image']
65 else:
68 else:
66 image = None
69 image = None
67
70
68 tags = []
71 tags = []
69
72
70 new_thread = thread_id == boards.models.NO_PARENT
73 new_thread = thread_id == boards.models.NO_PARENT
71 if new_thread:
74 if new_thread:
72 tag_strings = data['tags']
75 tag_strings = data['tags']
73
76
74 if tag_strings:
77 if tag_strings:
75 tag_strings = tag_strings.split(' ')
78 tag_strings = tag_strings.split(' ')
76 for tag_name in tag_strings:
79 for tag_name in tag_strings:
77 tag_name = tag_name.strip()
80 tag_name = tag_name.strip()
78 if len(tag_name) > 0:
81 if len(tag_name) > 0:
79 tag, created = Tag.objects.get_or_create(name=tag_name)
82 tag, created = Tag.objects.get_or_create(name=tag_name)
80 tags.append(tag)
83 tags.append(tag)
81
84
82 # TODO Add a possibility to define a link image instead of an image file.
85 # TODO Add a possibility to define a link image instead of an image file.
83 # If a link is given, download the image automatically.
86 # If a link is given, download the image automatically.
84
87
85 post = Post.objects.create_post(title=title, text=text, ip=ip,
88 post = Post.objects.create_post(title=title, text=text, ip=ip,
86 parent_id=thread_id, image=image,
89 parent_id=thread_id, image=image,
87 tags=tags)
90 tags=tags)
88
91
89 thread_to_show = (post.id if new_thread else thread_id)
92 thread_to_show = (post.id if new_thread else thread_id)
90
93
91 if new_thread:
94 if new_thread:
92 return redirect(thread, post_id=thread_to_show)
95 return redirect(thread, post_id=thread_to_show)
93 else:
96 else:
94 return redirect(reverse(thread,
97 return redirect(reverse(thread,
95 kwargs={'post_id': thread_to_show}) + '#'
98 kwargs={'post_id': thread_to_show}) + '#'
96 + str(post.id))
99 + str(post.id))
97
100
98
101
99 def tag(request, tag_name, page=0):
102 def tag(request, tag_name, page=0):
100 """Get all tag threads (posts without a parent)."""
103 """Get all tag threads (posts without a parent)."""
101
104
102 tag = get_object_or_404(Tag, name=tag_name)
105 tag = get_object_or_404(Tag, name=tag_name)
103 threads = Post.objects.get_threads(tag=tag, page=int(page))
106 threads = Post.objects.get_threads(tag=tag, page=int(page))
104
107
105 if request.method == 'POST':
108 if request.method == 'POST':
106 form = ThreadForm(request.POST, request.FILES,
109 form = ThreadForm(request.POST, request.FILES,
107 error_class=PlainErrorList)
110 error_class=PlainErrorList)
108 if form.is_valid():
111 if form.is_valid():
109 return _new_post(request, form)
112 return _new_post(request, form)
110 else:
113 else:
111 form = forms.ThreadForm(initial={'tags': tag_name},
114 form = forms.ThreadForm(initial={'tags': tag_name},
112 error_class=PlainErrorList)
115 error_class=PlainErrorList)
113
116
114 context = _init_default_context(request)
117 context = _init_default_context(request)
115 context['threads'] = None if len(threads) == 0 else threads
118 context['threads'] = None if len(threads) == 0 else threads
116 context['tag'] = tag_name
119 context['tag'] = tag_name
117 context['pages'] = range(Post.objects.get_thread_page_count(tag=tag))
120 context['pages'] = range(Post.objects.get_thread_page_count(tag=tag))
118
121
119 context['form'] = form
122 context['form'] = form
120
123
121 return render(request, 'boards/posting_general.html',
124 return render(request, 'boards/posting_general.html',
122 context)
125 context)
123
126
124
127
125 def thread(request, post_id):
128 def thread(request, post_id):
126 """Get all thread posts"""
129 """Get all thread posts"""
127
130
128 if utils.need_include_captcha(request):
131 if utils.need_include_captcha(request):
129 postFormClass = PostCaptchaForm
132 postFormClass = PostCaptchaForm
130 kwargs = {'request': request}
133 kwargs = {'request': request}
131 else:
134 else:
132 postFormClass = PostForm
135 postFormClass = PostForm
133 kwargs = {}
136 kwargs = {}
134
137
135 if request.method == 'POST':
138 if request.method == 'POST':
136 form = postFormClass(request.POST, request.FILES,
139 form = postFormClass(request.POST, request.FILES,
137 error_class=PlainErrorList, **kwargs)
140 error_class=PlainErrorList, **kwargs)
138 form.session = request.session
141 form.session = request.session
139
142
140 if form.is_valid():
143 if form.is_valid():
141 return _new_post(request, form, post_id)
144 return _new_post(request, form, post_id)
142 else:
145 else:
143 form = postFormClass(error_class=PlainErrorList, **kwargs)
146 form = postFormClass(error_class=PlainErrorList, **kwargs)
144
147
145 posts = Post.objects.get_thread(post_id)
148 posts = Post.objects.get_thread(post_id)
146
149
147 context = _init_default_context(request)
150 context = _init_default_context(request)
148
151
149 context['posts'] = posts
152 context['posts'] = posts
150 context['form'] = form
153 context['form'] = form
151 context['bumpable'] = posts[0].can_bump()
154 context['bumpable'] = posts[0].can_bump()
152
155
153 return render(request, 'boards/thread.html', context)
156 return render(request, 'boards/thread.html', context)
154
157
155
158
156 def login(request):
159 def login(request):
157 """Log in with user id"""
160 """Log in with user id"""
158
161
159 context = _init_default_context(request)
162 context = _init_default_context(request)
160
163
161 if request.method == 'POST':
164 if request.method == 'POST':
162 form = LoginForm(request.POST, request.FILES,
165 form = LoginForm(request.POST, request.FILES,
163 error_class=PlainErrorList)
166 error_class=PlainErrorList)
164 if form.is_valid():
167 if form.is_valid():
165 user = User.objects.get(user_id=form.cleaned_data['user_id'])
168 user = User.objects.get(user_id=form.cleaned_data['user_id'])
166 request.session['user_id'] = user.id
169 request.session['user_id'] = user.id
167 return redirect(index)
170 return redirect(index)
168
171
169 else:
172 else:
170 form = LoginForm()
173 form = LoginForm()
171
174
172 context['form'] = form
175 context['form'] = form
173
176
174 return render(request, 'boards/login.html', context)
177 return render(request, 'boards/login.html', context)
175
178
176
179
177 def settings(request):
180 def settings(request):
178 """User's settings"""
181 """User's settings"""
179
182
180 context = _init_default_context(request)
183 context = _init_default_context(request)
181
184
182 if request.method == 'POST':
185 if request.method == 'POST':
183 form = SettingsForm(request.POST)
186 form = SettingsForm(request.POST)
184 if form.is_valid():
187 if form.is_valid():
185 selected_theme = form.cleaned_data['theme']
188 selected_theme = form.cleaned_data['theme']
186
189
187 user = _get_user(request)
190 user = _get_user(request)
188 user.save_setting('theme', selected_theme)
191 user.save_setting('theme', selected_theme)
189
192
190 return redirect(settings)
193 return redirect(settings)
191 else:
194 else:
192 selected_theme = _get_theme(request)
195 selected_theme = _get_theme(request)
193 form = SettingsForm(initial={'theme': selected_theme})
196 form = SettingsForm(initial={'theme': selected_theme})
194 context['form'] = form
197 context['form'] = form
195
198
196 return render(request, 'boards/settings.html', context)
199 return render(request, 'boards/settings.html', context)
197
200
198
201
199 def all_tags(request):
202 def all_tags(request):
200 """All tags list"""
203 """All tags list"""
201
204
202 context = _init_default_context(request)
205 context = _init_default_context(request)
203 context['all_tags'] = Tag.objects.get_not_empty_tags()
206 context['all_tags'] = Tag.objects.get_not_empty_tags()
204
207
205 return render(request, 'boards/tags.html', context)
208 return render(request, 'boards/tags.html', context)
206
209
207
210
208 def jump_to_post(request, post_id):
211 def jump_to_post(request, post_id):
209 """Determine thread in which the requested post is and open it's page"""
212 """Determine thread in which the requested post is and open it's page"""
210
213
211 post = get_object_or_404(Post, id=post_id)
214 post = get_object_or_404(Post, id=post_id)
212
215
213 if boards.models.NO_PARENT == post.parent:
216 if boards.models.NO_PARENT == post.parent:
214 return redirect(thread, post_id=post.id)
217 return redirect(thread, post_id=post.id)
215 else:
218 else:
216 parent_thread = get_object_or_404(Post, id=post.parent)
219 parent_thread = get_object_or_404(Post, id=post.parent)
217 return redirect(reverse(thread, kwargs={'post_id': parent_thread.id})
220 return redirect(reverse(thread, kwargs={'post_id': parent_thread.id})
218 + '#' + str(post.id))
221 + '#' + str(post.id))
219
222
220
223
221 def authors(request):
224 def authors(request):
222 context = _init_default_context(request)
225 context = _init_default_context(request)
223 context['authors'] = boards.authors.authors
226 context['authors'] = boards.authors.authors
224
227
225 return render(request, 'boards/authors.html', context)
228 return render(request, 'boards/authors.html', context)
226
229
227
230
228 def delete(request, post_id):
231 def delete(request, post_id):
229 user = _get_user(request)
232 user = _get_user(request)
230 post = get_object_or_404(Post, id=post_id)
233 post = get_object_or_404(Post, id=post_id)
231
234
232 if user.is_moderator():
235 if user.is_moderator():
233 # TODO Show confirmation page before deletion
236 # TODO Show confirmation page before deletion
234 Post.objects.delete_post(post)
237 Post.objects.delete_post(post)
235
238
236 if NO_PARENT == post.parent:
239 if NO_PARENT == post.parent:
237 return _redirect_to_next(request)
240 return _redirect_to_next(request)
238 else:
241 else:
239 return redirect(thread, post_id=post.parent)
242 return redirect(thread, post_id=post.parent)
240
243
241
244
242 def ban(request, post_id):
245 def ban(request, post_id):
243 user = _get_user(request)
246 user = _get_user(request)
244 post = get_object_or_404(Post, id=post_id)
247 post = get_object_or_404(Post, id=post_id)
245
248
246 if user.is_moderator():
249 if user.is_moderator():
247 # TODO Show confirmation page before ban
250 # TODO Show confirmation page before ban
248 Ban.objects.get_or_create(ip=post.poster_ip)
251 Ban.objects.get_or_create(ip=post.poster_ip)
249
252
250 return _redirect_to_next(request)
253 return _redirect_to_next(request)
251
254
252
255
253 def you_are_banned(request):
256 def you_are_banned(request):
254 context = _init_default_context(request)
257 context = _init_default_context(request)
255 return render(request, 'boards/staticpages/banned.html', context)
258 return render(request, 'boards/staticpages/banned.html', context)
256
259
257
260
258 def page_404(request):
261 def page_404(request):
259 context = _init_default_context(request)
262 context = _init_default_context(request)
260 return render(request, 'boards/404.html', context)
263 return render(request, 'boards/404.html', context)
261
264
262
265
263 def tag_subscribe(request, tag_name):
266 def tag_subscribe(request, tag_name):
264 user = _get_user(request)
267 user = _get_user(request)
265 tag = get_object_or_404(Tag, name=tag_name)
268 tag = get_object_or_404(Tag, name=tag_name)
266
269
267 if not tag in user.fav_tags.all():
270 if not tag in user.fav_tags.all():
268 user.fav_tags.add(tag)
271 user.fav_tags.add(tag)
269
272
270 return redirect(all_tags)
273 return redirect(all_tags)
271
274
272
275
273 def tag_unsubscribe(request, tag_name):
276 def tag_unsubscribe(request, tag_name):
274 user = _get_user(request)
277 user = _get_user(request)
275 tag = get_object_or_404(Tag, name=tag_name)
278 tag = get_object_or_404(Tag, name=tag_name)
276
279
277 if tag in user.fav_tags.all():
280 if tag in user.fav_tags.all():
278 user.fav_tags.remove(tag)
281 user.fav_tags.remove(tag)
279
282
280 return redirect(all_tags)
283 return redirect(all_tags)
281
284
282
285
283 def static_page(request, name):
286 def static_page(request, name):
284 context = _init_default_context(request)
287 context = _init_default_context(request)
285 return render(request, 'boards/staticpages/' + name + '.html', context)
288 return render(request, 'boards/staticpages/' + name + '.html', context)
286
289
287
290
288 def _get_theme(request, user=None):
291 def _get_theme(request, user=None):
289 """Get user's CSS theme"""
292 """Get user's CSS theme"""
290
293
291 if not user:
294 if not user:
292 user = _get_user(request)
295 user = _get_user(request)
293 theme = user.get_setting('theme')
296 theme = user.get_setting('theme')
294 if not theme:
297 if not theme:
295 theme = neboard.settings.DEFAULT_THEME
298 theme = neboard.settings.DEFAULT_THEME
296
299
297 return theme
300 return theme
298
301
299
302
300 def _get_client_ip(request):
303 def _get_client_ip(request):
301 x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
304 x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
302 if x_forwarded_for:
305 if x_forwarded_for:
303 ip = x_forwarded_for.split(',')[-1].strip()
306 ip = x_forwarded_for.split(',')[-1].strip()
304 else:
307 else:
305 ip = request.META.get('REMOTE_ADDR')
308 ip = request.META.get('REMOTE_ADDR')
306 return ip
309 return ip
307
310
308
311
309 def _init_default_context(request):
312 def _init_default_context(request):
310 """Create context with default values that are used in most views"""
313 """Create context with default values that are used in most views"""
311
314
312 context = RequestContext(request)
315 context = RequestContext(request)
313
316
314 user = _get_user(request)
317 user = _get_user(request)
315 context['user'] = user
318 context['user'] = user
316 context['tags'] = user.get_sorted_fav_tags()
319 context['tags'] = user.get_sorted_fav_tags()
317 context['theme'] = _get_theme(request, user)
320 context['theme'] = _get_theme(request, user)
318
321
319 return context
322 return context
320
323
321
324
322 def _get_user(request):
325 def _get_user(request):
323 """Get current user from the session"""
326 """Get current user from the session"""
324
327
325 session = request.session
328 session = request.session
326 if not 'user_id' in session:
329 if not 'user_id' in session:
327 request.session.save()
330 request.session.save()
328
331
329 md5 = hashlib.md5()
332 md5 = hashlib.md5()
330 md5.update(session.session_key)
333 md5.update(session.session_key)
331 new_id = md5.hexdigest()
334 new_id = md5.hexdigest()
332
335
333 time_now = timezone.now()
336 time_now = timezone.now()
334 user = User.objects.create(user_id=new_id, rank=RANK_USER,
337 user = User.objects.create(user_id=new_id, rank=RANK_USER,
335 registration_time=time_now,
338 registration_time=time_now,
336 last_access_time=time_now)
339 last_access_time=time_now)
337
340
338 session['user_id'] = user.id
341 session['user_id'] = user.id
339 else:
342 else:
340 user = User.objects.get(id=session['user_id'])
343 user = User.objects.get(id=session['user_id'])
341 user.last_access_time = timezone.now()
344 user.last_access_time = timezone.now()
342 user.save()
345 user.save()
343
346
344 return user
347 return user
345
348
346
349
347 def _redirect_to_next(request):
350 def _redirect_to_next(request):
348 if 'next' in request.GET:
351 if 'next' in request.GET:
349 next_page = request.GET['next']
352 next_page = request.GET['next']
350 return HttpResponseRedirect(next_page)
353 return HttpResponseRedirect(next_page)
351 else:
354 else:
352 return redirect(index)
355 return redirect(index)
General Comments 0
You need to be logged in to leave comments. Login now