##// END OF EJS Templates
Moved login view to a separate class. Refactored thread and all threads views
neko259 -
r544:5f217adc 1.7-dev
parent child Browse files
Show More
@@ -0,0 +1,30 b''
1 from django.shortcuts import render, redirect
2 from boards.forms import LoginForm, PlainErrorList
3 from boards.models import User
4 from boards.views.base import BaseBoardView, PARAMETER_FORM
5
6 __author__ = 'neko259'
7
8
9 class LoginView(BaseBoardView):
10
11 def get(self, request, form=None):
12 context = self.get_context_data(request=request)
13
14 if not form:
15 form = LoginForm()
16 context[PARAMETER_FORM] = form
17
18 return render(request, 'boards/login.html', context)
19
20 def post(self, request):
21 form = LoginForm(request.POST, request.FILES,
22 error_class=PlainErrorList)
23 form.session = request.session
24
25 if form.is_valid():
26 user = User.objects.get(user_id=form.cleaned_data['user_id'])
27 request.session['user_id'] = user.id
28 return redirect('index')
29 else:
30 return self.get(request, form)
@@ -1,96 +1,96 b''
1 1 {% load i18n %}
2 2 {% load board %}
3 3 {% load cache %}
4 4
5 5 {% get_current_language as LANGUAGE_CODE %}
6 6
7 {% cache 60 post post.id post.thread_new.last_edit_time truncated moderator LANGUAGE_CODE %}
7 {% cache 300 post post.id post.thread_new.last_edit_time truncated moderator LANGUAGE_CODE need_open_link %}
8 8 {% spaceless %}
9 9 {% with thread=post.thread_new %}
10 10 {% if thread.archived %}
11 11 <div class="post archive_post" id="{{ post.id }}">
12 12 {% elif thread.can_bump %}
13 13 <div class="post" id="{{ post.id }}">
14 14 {% else %}
15 15 <div class="post dead_post" id="{{ post.id }}">
16 16 {% endif %}
17 17
18 18 {% if post.image %}
19 19 <div class="image">
20 20 <a
21 21 class="thumb"
22 22 href="{{ post.image.url }}"><img
23 23 src="{{ post.image.url_200x150 }}"
24 24 alt="{{ post.id }}"
25 25 width="{{ post.image_pre_width }}"
26 26 height="{{ post.image_pre_height }}"
27 27 data-width="{{ post.image_width }}"
28 28 data-height="{{ post.image_height }}"/>
29 29 </a>
30 30 </div>
31 31 {% endif %}
32 32 <div class="message">
33 33 <div class="post-info">
34 34 <span class="title">{{ post.title }}</span>
35 35 <a class="post_id" href="{% post_url post.id %}">
36 36 ({{ post.id }}) </a>
37 37 [<span class="pub_time">{{ post.pub_time }}</span>]
38 38 {% if thread.archived %}
39 39 β€” [{{ thread.bump_time }}]
40 40 {% endif %}
41 41 {% if not truncated %}
42 42 [<a href="#" onclick="javascript:addQuickReply('{{ post.id }}')
43 43 ; return false;">&gt;&gt;</a>]
44 44 {% endif %}
45 45 {% if post.is_opening and need_open_link %}
46 46 {% if post.thread_new.archived %}
47 47 [<a class="link" href="{% url 'thread' post.id %}">{% trans "Open" %}</a>]
48 48 {% else %}
49 49 [<a class="link" href="{% url 'thread' post.id %}#form">{% trans "Reply" %}</a>]
50 50 {% endif %}
51 51 {% endif %}
52 52
53 53 {% if moderator %}
54 54 <span class="moderator_info">
55 55 [<a href="{% url 'delete' post_id=post.id %}"
56 56 >{% trans 'Delete' %}</a>]
57 57 ({{ post.poster_ip }})
58 58 [<a href="{% url 'ban' post_id=post.id %}?next={{ request.path }}"
59 59 >{% trans 'Ban IP' %}</a>]
60 60 </span>
61 61 {% endif %}
62 62 </div>
63 63 {% autoescape off %}
64 64 {% if truncated %}
65 65 {{ post.text.rendered|truncatewords_html:50 }}
66 66 {% else %}
67 67 {{ post.text.rendered }}
68 68 {% endif %}
69 69 {% endautoescape %}
70 70 {% if post.is_referenced %}
71 71 <div class="refmap">
72 72 {% trans "Replies" %}:
73 73 {% for ref_post in post.get_sorted_referenced_posts %}
74 74 <a href="{% post_url ref_post.id %}">&gt;&gt;{{ ref_post.id }}</a
75 75 >{% if not forloop.last %},{% endif %}
76 76 {% endfor %}
77 77 </div>
78 78 {% endif %}
79 79 </div>
80 80 {% if post.is_opening and thread.tags.exists %}
81 81 <div class="metadata">
82 82 {% if post.is_opening and need_open_link %}
83 83 {{ thread.get_images_count }} {% trans 'images' %}.
84 84 {% endif %}
85 85 <span class="tags">
86 86 {% for tag in thread.get_tags %}
87 87 <a class="tag" href="{% url 'tag' tag.name %}">
88 88 #{{ tag.name }}</a>{% if not forloop.last %},{% endif %}
89 89 {% endfor %}
90 90 </span>
91 91 </div>
92 92 {% endif %}
93 93 </div>
94 94 {% endwith %}
95 95 {% endspaceless %}
96 {% endcache %} No newline at end of file
96 {% endcache %}
@@ -1,76 +1,76 b''
1 1 from django.conf.urls import patterns, url, include
2 2 from boards import views
3 3 from boards.rss import AllThreadsFeed, TagThreadsFeed, ThreadPostsFeed
4 from boards.views import api, tag_threads, all_threads, archived_threads
4 from boards.views import api, tag_threads, all_threads, archived_threads, login
5 5
6 6 js_info_dict = {
7 7 'packages': ('boards',),
8 8 }
9 9
10 10 urlpatterns = patterns('',
11 11
12 12 # /boards/
13 13 url(r'^$', all_threads.AllThreadsView.as_view(), name='index'),
14 14 # /boards/page/
15 15 url(r'^page/(?P<page>\w+)/$', all_threads.AllThreadsView.as_view(),
16 16 name='index'),
17 17
18 18 url(r'^archive/$', archived_threads.ArchiveView.as_view(), name='archive'),
19 19 url(r'^archive/page/(?P<page>\w+)/$',
20 20 archived_threads.ArchiveView.as_view(), name='archive'),
21 21
22 22 # login page
23 url(r'^login/$', views.login, name='login'),
23 url(r'^login/$', login.LoginView.as_view(), name='login'),
24 24
25 25 # /boards/tag/tag_name/
26 26 url(r'^tag/(?P<tag_name>\w+)/$', tag_threads.TagView.as_view(),
27 27 name='tag'),
28 28 # /boards/tag/tag_id/page/
29 29 url(r'^tag/(?P<tag_name>\w+)/page/(?P<page>\w+)/$',
30 30 tag_threads.TagView.as_view(), name='tag'),
31 31
32 32 # /boards/tag/tag_name/unsubscribe/
33 33 url(r'^tag/(?P<tag_name>\w+)/subscribe/$', views.tag_subscribe,
34 34 name='tag_subscribe'),
35 35 # /boards/tag/tag_name/unsubscribe/
36 36 url(r'^tag/(?P<tag_name>\w+)/unsubscribe/$', views.tag_unsubscribe,
37 37 name='tag_unsubscribe'),
38 38
39 39 # /boards/thread/
40 40 url(r'^thread/(?P<post_id>\w+)/$', views.thread.ThreadView.as_view(),
41 41 name='thread'),
42 42 url(r'^thread/(?P<post_id>\w+)/(?P<mode>\w+)/$', views.thread.ThreadView
43 43 .as_view(), name='thread_mode'),
44 44 url(r'^settings/$', views.settings, name='settings'),
45 45 url(r'^tags/$', views.all_tags, name='tags'),
46 46 url(r'^captcha/', include('captcha.urls')),
47 47 url(r'^jump/(?P<post_id>\w+)/$', views.jump_to_post, name='jumper'),
48 48 url(r'^authors/$', views.authors, name='authors'),
49 49 url(r'^delete/(?P<post_id>\w+)/$', views.delete, name='delete'),
50 50 url(r'^ban/(?P<post_id>\w+)/$', views.ban, name='ban'),
51 51
52 52 url(r'^banned/$', views.banned.BannedView.as_view, name='banned'),
53 53 url(r'^staticpage/(?P<name>\w+)/$', views.static_page, name='staticpage'),
54 54
55 55 # RSS feeds
56 56 url(r'^rss/$', AllThreadsFeed()),
57 57 url(r'^page/(?P<page>\w+)/rss/$', AllThreadsFeed()),
58 58 url(r'^tag/(?P<tag_name>\w+)/rss/$', TagThreadsFeed()),
59 59 url(r'^tag/(?P<tag_name>\w+)/page/(?P<page>\w+)/rss/$', TagThreadsFeed()),
60 60 url(r'^thread/(?P<post_id>\w+)/rss/$', ThreadPostsFeed()),
61 61
62 62 # i18n
63 63 url(r'^jsi18n/$', 'boards.views.cached_js_catalog', js_info_dict, name='js_info_dict'),
64 64
65 65 # API
66 66 url(r'^api/post/(?P<post_id>\w+)/$', api.get_post, name="get_post"),
67 67 url(r'^api/diff_thread/(?P<thread_id>\w+)/(?P<last_update_time>\w+)/$',
68 68 api.api_get_threaddiff, name="get_thread_diff"),
69 69 url(r'^api/threads/(?P<count>\w+)/$', api.api_get_threads,
70 70 name='get_threads'),
71 71 url(r'^api/tags/$', api.api_get_tags, name='get_tags'),
72 72 url(r'^api/thread/(?P<opening_post_id>\w+)/$', api.api_get_thread_posts,
73 73 name='get_thread'),
74 74 url(r'^api/add_post/(?P<opening_post_id>\w+)/$', api.api_add_post, name='add_post'),
75 75
76 76 )
@@ -1,356 +1,283 b''
1 from datetime import datetime, timedelta
2
3 from django.db.models import Count
4
5 1 __author__ = 'neko259'
6 2
7 3 import hashlib
8 import string
9 import re
10 4
11 5 from django.core import serializers
12 6 from django.core.urlresolvers import reverse
13 7 from django.http import HttpResponseRedirect
14 8 from django.http.response import HttpResponse
15 9 from django.template import RequestContext
16 10 from django.shortcuts import render, redirect, get_object_or_404
17 11 from django.utils import timezone
18 12 from django.db import transaction
19 13 from django.views.decorators.cache import cache_page
20 14 from django.views.i18n import javascript_catalog
21 15
22 16 import boards
23 from boards import utils
24 17 from boards.forms import SettingsForm, PlainErrorList, \
25 LoginForm, ModeratorSettingsForm
18 ModeratorSettingsForm
26 19 from boards.models import Post, Tag, Ban, User
27 from boards.models.post import SETTING_MODERATE, REGEX_REPLY
20 from boards.models.post import SETTING_MODERATE
28 21 from boards.models.user import RANK_USER
29 22 from boards import authors
30 23 import neboard
31
32 24 import all_threads
33 25
34 26
35 27 BAN_REASON_SPAM = 'Autoban: spam bot'
36 28
37 29 DEFAULT_PAGE = 1
38 30
39 31
40 def login(request):
41 """Log in with user id"""
42
43 context = _init_default_context(request)
44
45 if request.method == 'POST':
46 form = LoginForm(request.POST, request.FILES,
47 error_class=PlainErrorList)
48 form.session = request.session
49
50 if form.is_valid():
51 user = User.objects.get(user_id=form.cleaned_data['user_id'])
52 request.session['user_id'] = user.id
53 return redirect('index')
54
55 else:
56 form = LoginForm()
57
58 context['form'] = form
59
60 return render(request, 'boards/login.html', context)
61
62
63 32 def settings(request):
64 33 """User's settings"""
65 34
66 35 context = _init_default_context(request)
67 36 user = _get_user(request)
68 37 is_moderator = user.is_moderator()
69 38
70 39 if request.method == 'POST':
71 40 with transaction.atomic():
72 41 if is_moderator:
73 42 form = ModeratorSettingsForm(request.POST,
74 43 error_class=PlainErrorList)
75 44 else:
76 45 form = SettingsForm(request.POST, error_class=PlainErrorList)
77 46
78 47 if form.is_valid():
79 48 selected_theme = form.cleaned_data['theme']
80 49
81 50 user.save_setting('theme', selected_theme)
82 51
83 52 if is_moderator:
84 53 moderate = form.cleaned_data['moderate']
85 54 user.save_setting(SETTING_MODERATE, moderate)
86 55
87 56 return redirect(settings)
88 57 else:
89 58 selected_theme = _get_theme(request)
90 59
91 60 if is_moderator:
92 61 form = ModeratorSettingsForm(initial={'theme': selected_theme,
93 62 'moderate': context['moderator']},
94 63 error_class=PlainErrorList)
95 64 else:
96 65 form = SettingsForm(initial={'theme': selected_theme},
97 66 error_class=PlainErrorList)
98 67
99 68 context['form'] = form
100 69
101 70 return render(request, 'boards/settings.html', context)
102 71
103 72
104 73 def all_tags(request):
105 74 """All tags list"""
106 75
107 76 context = _init_default_context(request)
108 77 context['all_tags'] = Tag.objects.get_not_empty_tags()
109 78
110 79 return render(request, 'boards/tags.html', context)
111 80
112 81
113 82 def jump_to_post(request, post_id):
114 83 """Determine thread in which the requested post is and open it's page"""
115 84
116 85 post = get_object_or_404(Post, id=post_id)
117 86
118 87 if not post.thread:
119 88 return redirect('thread', post_id=post.id)
120 89 else:
121 90 return redirect(reverse('thread', kwargs={'post_id': post.thread.id})
122 91 + '#' + str(post.id))
123 92
124 93
125 94 def authors(request):
126 95 """Show authors list"""
127 96
128 97 context = _init_default_context(request)
129 98 context['authors'] = boards.authors.authors
130 99
131 100 return render(request, 'boards/authors.html', context)
132 101
133 102
134 103 @transaction.atomic
135 104 def delete(request, post_id):
136 105 """Delete post"""
137 106
138 107 user = _get_user(request)
139 108 post = get_object_or_404(Post, id=post_id)
140 109
141 110 if user.is_moderator():
142 111 # TODO Show confirmation page before deletion
143 112 Post.objects.delete_post(post)
144 113
145 114 if not post.thread:
146 115 return _redirect_to_next(request)
147 116 else:
148 117 return redirect('thread', post_id=post.thread.id)
149 118
150 119
151 120 @transaction.atomic
152 121 def ban(request, post_id):
153 122 """Ban user"""
154 123
155 124 user = _get_user(request)
156 125 post = get_object_or_404(Post, id=post_id)
157 126
158 127 if user.is_moderator():
159 128 # TODO Show confirmation page before ban
160 129 ban, created = Ban.objects.get_or_create(ip=post.poster_ip)
161 130 if created:
162 131 ban.reason = 'Banned for post ' + str(post_id)
163 132 ban.save()
164 133
165 134 return _redirect_to_next(request)
166 135
167 136
168 137 def page_404(request):
169 138 """Show page 404 (not found error)"""
170 139
171 140 context = _init_default_context(request)
172 141 return render(request, 'boards/404.html', context)
173 142
174 143
175 144 @transaction.atomic
176 145 def tag_subscribe(request, tag_name):
177 146 """Add tag to favorites"""
178 147
179 148 user = _get_user(request)
180 149 tag = get_object_or_404(Tag, name=tag_name)
181 150
182 151 if not tag in user.fav_tags.all():
183 152 user.add_tag(tag)
184 153
185 154 return _redirect_to_next(request)
186 155
187 156
188 157 @transaction.atomic
189 158 def tag_unsubscribe(request, tag_name):
190 159 """Remove tag from favorites"""
191 160
192 161 user = _get_user(request)
193 162 tag = get_object_or_404(Tag, name=tag_name)
194 163
195 164 if tag in user.fav_tags.all():
196 165 user.remove_tag(tag)
197 166
198 167 return _redirect_to_next(request)
199 168
200 169
201 170 def static_page(request, name):
202 171 """Show a static page that needs only tags list and a CSS"""
203 172
204 173 context = _init_default_context(request)
205 174 return render(request, 'boards/staticpages/' + name + '.html', context)
206 175
207 176
208 177 def api_get_post(request, post_id):
209 178 """
210 179 Get the JSON of a post. This can be
211 180 used as and API for external clients.
212 181 """
213 182
214 183 post = get_object_or_404(Post, id=post_id)
215 184
216 185 json = serializers.serialize("json", [post], fields=(
217 186 "pub_time", "_text_rendered", "title", "text", "image",
218 187 "image_width", "image_height", "replies", "tags"
219 188 ))
220 189
221 190 return HttpResponse(content=json)
222 191
223 192
224 193 @cache_page(86400)
225 194 def cached_js_catalog(request, domain='djangojs', packages=None):
226 195 return javascript_catalog(request, domain, packages)
227 196
228 197
229 198 # TODO This method is deprecated and should be removed after switching to
230 199 # class-based view
231 200 def _get_theme(request, user=None):
232 201 """Get user's CSS theme"""
233 202
234 203 if not user:
235 204 user = _get_user(request)
236 205 theme = user.get_setting('theme')
237 206 if not theme:
238 207 theme = neboard.settings.DEFAULT_THEME
239 208
240 209 return theme
241 210
242 211
243 212 # TODO This method is deprecated and should be removed after switching to
244 213 # class-based view
245 214 def _init_default_context(request):
246 215 """Create context with default values that are used in most views"""
247 216
248 217 context = RequestContext(request)
249 218
250 219 user = _get_user(request)
251 220 context['user'] = user
252 221 context['tags'] = user.get_sorted_fav_tags()
253 222 context['posts_per_day'] = float(Post.objects.get_posts_per_day())
254 223
255 224 theme = _get_theme(request, user)
256 225 context['theme'] = theme
257 226 context['theme_css'] = 'css/' + theme + '/base_page.css'
258 227
259 228 # This shows the moderator panel
260 229 moderate = user.get_setting(SETTING_MODERATE)
261 230 if moderate == 'True':
262 231 context['moderator'] = user.is_moderator()
263 232 else:
264 233 context['moderator'] = False
265 234
266 235 return context
267 236
268 237
269 238 # TODO This method is deprecated and should be removed after switching to
270 239 # class-based view
271 240 def _get_user(request):
272 241 """
273 242 Get current user from the session. If the user does not exist, create
274 243 a new one.
275 244 """
276 245
277 246 session = request.session
278 247 if not 'user_id' in session:
279 248 request.session.save()
280 249
281 250 md5 = hashlib.md5()
282 251 md5.update(session.session_key)
283 252 new_id = md5.hexdigest()
284 253
285 254 while User.objects.filter(user_id=new_id).exists():
286 255 md5.update(str(timezone.now()))
287 256 new_id = md5.hexdigest()
288 257
289 258 time_now = timezone.now()
290 259 user = User.objects.create(user_id=new_id, rank=RANK_USER,
291 260 registration_time=time_now)
292 261
293 262 # TODO This is just a test. This method should be removed
294 263 # _delete_old_users()
295 264
296 265 session['user_id'] = user.id
297 266 else:
298 267 user = User.objects.get(id=session['user_id'])
299 268
300 269 return user
301 270
302 271
303 272 def _redirect_to_next(request):
304 273 """
305 274 If a 'next' parameter was specified, redirect to the next page. This is
306 275 used when the user is required to return to some page after the current
307 276 view has finished its work.
308 277 """
309 278
310 279 if 'next' in request.GET:
311 280 next_page = request.GET['next']
312 281 return HttpResponseRedirect(next_page)
313 282 else:
314 return redirect('index')
315
316
317 @transaction.atomic
318 def _ban_current_user(request):
319 """Add current user to the IP ban list"""
320
321 ip = utils.get_client_ip(request)
322 ban, created = Ban.objects.get_or_create(ip=ip)
323 if created:
324 ban.can_read = False
325 ban.reason = BAN_REASON_SPAM
326 ban.save()
327
328
329 def _remove_invalid_links(text):
330 """
331 Replace invalid links in posts so that they won't be parsed.
332 Invalid links are links to non-existent posts
333 """
334
335 for reply_number in re.finditer(REGEX_REPLY, text):
336 post_id = reply_number.group(1)
337 post = Post.objects.filter(id=post_id)
338 if not post.exists():
339 text = string.replace(text, '>>' + post_id, post_id)
340
341 return text
342
343
344 def _get_template_thread(thread_to_show):
345 """Get template values for thread"""
346
347 last_replies = thread_to_show.get_last_replies()
348 skipped_replies_count = thread_to_show.get_replies().count() \
349 - len(last_replies) - 1
350 return {
351 'thread': thread_to_show,
352 'op': thread_to_show.get_replies()[0],
353 'bumpable': thread_to_show.can_bump(),
354 'last_replies': last_replies,
355 'skipped_replies': skipped_replies_count,
356 }
283 return redirect('index') No newline at end of file
@@ -1,134 +1,125 b''
1 1 import string
2 2
3 3 from django.core.paginator import Paginator
4 4 from django.core.urlresolvers import reverse
5 5 from django.db import transaction
6 6 from django.shortcuts import render, redirect
7 7
8 8 from boards import utils
9 9 from boards.forms import ThreadForm, PlainErrorList
10 10 from boards.models import Post, Thread, Ban, Tag
11 11 from boards.views.banned import BannedView
12 12 from boards.views.base import BaseBoardView, PARAMETER_FORM
13 13 from boards.views.posting_mixin import PostMixin
14 14 import neboard
15 15
16 16 PARAMETER_CURRENT_PAGE = 'current_page'
17 17
18 18 PARAMETER_PAGINATOR = 'paginator'
19 19
20 20 PARAMETER_THREADS = 'threads'
21 21
22 22 TEMPLATE = 'boards/posting_general.html'
23 23 DEFAULT_PAGE = 1
24 24
25 25
26 26 class AllThreadsView(PostMixin, BaseBoardView):
27 27
28 def get(self, request, page=DEFAULT_PAGE):
28 def get(self, request, page=DEFAULT_PAGE, form=None):
29 29 context = self.get_context_data(request=request)
30 30
31 form = ThreadForm(error_class=PlainErrorList)
31 if not form:
32 form = ThreadForm(error_class=PlainErrorList)
32 33
33 34 paginator = Paginator(self.get_threads(),
34 35 neboard.settings.THREADS_PER_PAGE)
35 36
36 37 threads = paginator.page(page).object_list
37 38
38 39 context[PARAMETER_THREADS] = threads
39 40 context[PARAMETER_FORM] = form
40 41
41 42 self._get_page_context(paginator, context, page)
42 43
43 44 return render(request, TEMPLATE, context)
44 45
45 46 def post(self, request, page=DEFAULT_PAGE):
46 47 context = self.get_context_data(request=request)
47 48
48 49 form = ThreadForm(request.POST, request.FILES,
49 50 error_class=PlainErrorList)
50 51 form.session = request.session
51 52
52 53 if form.is_valid():
53 54 return self._new_post(request, form)
54 55 if form.need_to_ban:
55 56 # Ban user because he is suspected to be a bot
56 57 self._ban_current_user(request)
57 58
58 paginator = Paginator(self.get_threads(),
59 neboard.settings.THREADS_PER_PAGE)
60
61 threads = paginator.page(page).object_list
62
63 context[PARAMETER_THREADS] = threads
64 context[PARAMETER_FORM] = form
65
66 self._get_page_context(paginator, context, page)
67
68 return render(request, TEMPLATE, context)
59 return self.get(request, page, form)
69 60
70 61 @staticmethod
71 62 def _get_page_context(paginator, context, page):
72 63 """
73 64 Get pagination context variables
74 65 """
75 66
76 67 context[PARAMETER_PAGINATOR] = paginator
77 68 context[PARAMETER_CURRENT_PAGE] = paginator.page(int(page))
78 69
79 70 # TODO This method should be refactored
80 71 @transaction.atomic
81 72 def _new_post(self, request, form, opening_post=None, html_response=True):
82 73 """
83 74 Add a new thread opening post.
84 75 """
85 76
86 77 ip = utils.get_client_ip(request)
87 78 is_banned = Ban.objects.filter(ip=ip).exists()
88 79
89 80 if is_banned:
90 81 if html_response:
91 82 return redirect(BannedView().as_view())
92 83 else:
93 84 return
94 85
95 86 data = form.cleaned_data
96 87
97 88 title = data['title']
98 89 text = data['text']
99 90
100 91 text = self._remove_invalid_links(text)
101 92
102 93 if 'image' in data.keys():
103 94 image = data['image']
104 95 else:
105 96 image = None
106 97
107 98 tags = []
108 99
109 100 tag_strings = data['tags']
110 101
111 102 if tag_strings:
112 103 tag_strings = tag_strings.split(' ')
113 104 for tag_name in tag_strings:
114 105 tag_name = string.lower(tag_name.strip())
115 106 if len(tag_name) > 0:
116 107 tag, created = Tag.objects.get_or_create(name=tag_name)
117 108 tags.append(tag)
118 109
119 110 post = Post.objects.create_post(title=title, text=text, ip=ip,
120 111 image=image, tags=tags,
121 112 user=self._get_user(request))
122 113
123 114 thread_to_show = (opening_post.id if opening_post else post.id)
124 115
125 116 if html_response:
126 117 if opening_post:
127 118 return redirect(
128 119 reverse('thread', kwargs={'post_id': thread_to_show}) +
129 120 '#' + str(post.id))
130 121 else:
131 122 return redirect('thread', post_id=thread_to_show)
132 123
133 124 def get_threads(self):
134 return Thread.objects.filter(archived=False) No newline at end of file
125 return Thread.objects.filter(archived=False)
@@ -1,149 +1,121 b''
1 1 import string
2 2 from django.core.urlresolvers import reverse
3 3 from django.db import transaction
4 4 from django.http import Http404
5 5 from django.shortcuts import get_object_or_404, render, redirect
6 6 from boards import utils
7 7 from boards.forms import PostForm, PlainErrorList
8 8 from boards.models import Post, Ban, Tag
9 9 from boards.views.banned import BannedView
10 10 from boards.views.base import BaseBoardView, PARAMETER_FORM
11 11 from boards.views.posting_mixin import PostMixin
12 12 import neboard
13 13
14 14 MODE_GALLERY = 'gallery'
15 15 MODE_NORMAL = 'normal'
16 16
17 17
18 18 class ThreadView(BaseBoardView, PostMixin):
19 19
20 def get(self, request, post_id, mode=MODE_NORMAL):
20 def get(self, request, post_id, mode=MODE_NORMAL, form=None):
21 21 opening_post = get_object_or_404(Post, id=post_id)
22 22
23 23 # If this is not OP, don't show it as it is
24 24 if not opening_post.is_opening():
25 25 raise Http404
26 26
27 form = PostForm(error_class=PlainErrorList)
27 if not form:
28 form = PostForm(error_class=PlainErrorList)
28 29
29 30 thread_to_show = opening_post.thread_new
30 31
31 32 context = self.get_context_data(request=request)
32 33
33 34 posts = thread_to_show.get_replies()
34 35 context[PARAMETER_FORM] = form
35 36 context["last_update"] = utils.datetime_to_epoch(
36 37 thread_to_show.last_edit_time)
37 38 context["thread"] = thread_to_show
38 39
39 40 if MODE_NORMAL == mode:
40 41 context['bumpable'] = thread_to_show.can_bump()
41 42 if context['bumpable']:
42 43 context['posts_left'] = neboard.settings.MAX_POSTS_PER_THREAD - posts \
43 44 .count()
44 45 context['bumplimit_progress'] = str(
45 46 float(context['posts_left']) /
46 47 neboard.settings.MAX_POSTS_PER_THREAD * 100)
47 48
48 49 context['posts'] = posts
49 50
50 51 document = 'boards/thread.html'
51 52 elif MODE_GALLERY == mode:
52 53 context['posts'] = posts.filter(image_width__gt=0)
53 54
54 55 document = 'boards/thread_gallery.html'
55 56 else:
56 57 raise Http404
57 58
58 59 return render(request, document, context)
59 60
60 61 def post(self, request, post_id, mode=MODE_NORMAL):
61 62 opening_post = get_object_or_404(Post, id=post_id)
62 63
63 64 # If this is not OP, don't show it as it is
64 65 if not opening_post.is_opening():
65 66 raise Http404
66 67
67 68 if not opening_post.thread_new.archived:
68 69 form = PostForm(request.POST, request.FILES,
69 70 error_class=PlainErrorList)
70 71 form.session = request.session
71 72
72 73 if form.is_valid():
73 74 return self.new_post(request, form, opening_post)
74 75 if form.need_to_ban:
75 76 # Ban user because he is suspected to be a bot
76 77 self._ban_current_user(request)
77 78
78 thread_to_show = opening_post.thread_new
79
80 context = self.get_context_data(request=request)
81
82 posts = thread_to_show.get_replies()
83 context[PARAMETER_FORM] = form
84 context["last_update"] = utils.datetime_to_epoch(
85 thread_to_show.last_edit_time)
86 context["thread"] = thread_to_show
87
88 if MODE_NORMAL == mode:
89 context['bumpable'] = thread_to_show.can_bump()
90 if context['bumpable']:
91 context['posts_left'] = neboard.settings.MAX_POSTS_PER_THREAD - posts \
92 .count()
93 context['bumplimit_progress'] = str(
94 float(context['posts_left']) /
95 neboard.settings.MAX_POSTS_PER_THREAD * 100)
96
97 context['posts'] = posts
98
99 document = 'boards/thread.html'
100 elif MODE_GALLERY == mode:
101 context['posts'] = posts.filter(image_width__gt=0)
102
103 document = 'boards/thread_gallery.html'
104 else:
105 raise Http404
106
107 return render(request, document, context)
79 return self.get(request, post_id, mode, form)
108 80
109 81 @transaction.atomic
110 82 def new_post(self, request, form, opening_post=None, html_response=True):
111 83 """Add a new post (in thread or as a reply)."""
112 84
113 85 ip = utils.get_client_ip(request)
114 86 is_banned = Ban.objects.filter(ip=ip).exists()
115 87
116 88 if is_banned:
117 89 if html_response:
118 90 return redirect(BannedView().as_view())
119 91 else:
120 92 return
121 93
122 94 data = form.cleaned_data
123 95
124 96 title = data['title']
125 97 text = data['text']
126 98
127 99 text = self._remove_invalid_links(text)
128 100
129 101 if 'image' in data.keys():
130 102 image = data['image']
131 103 else:
132 104 image = None
133 105
134 106 tags = []
135 107
136 108 post_thread = opening_post.thread_new
137 109
138 110 post = Post.objects.create_post(title=title, text=text, ip=ip,
139 111 thread=post_thread, image=image,
140 112 tags=tags,
141 113 user=self._get_user(request))
142 114
143 115 thread_to_show = (opening_post.id if opening_post else post.id)
144 116
145 117 if html_response:
146 118 if opening_post:
147 119 return redirect(reverse('thread',
148 120 kwargs={'post_id': thread_to_show}) + '#'
149 + str(post.id)) No newline at end of file
121 + str(post.id))
General Comments 0
You need to be logged in to leave comments. Login now