##// END OF EJS Templates
Using static template tag for resources.
neko259 -
r260:9648bcc7 default
parent child Browse files
Show More
@@ -1,56 +1,58 b''
1 1 {% load staticfiles %}
2 2 {% load i18n %}
3 {% load static from staticfiles %}
3 4
4 5 <!DOCTYPE html>
5 6 <html>
6 7 <head>
7 8 <link rel="stylesheet" type="text/css"
8 href="{{ STATIC_URL }}css/base.css" media="all"/>
9 href="{% static 'css/base.css' %}" media="all"/>
9 10 <link rel="stylesheet" type="text/css"
10 href="{{ STATIC_URL }}css/{{ theme }}/base_page.css?6" media="all"/>
11 <link rel="alternate" type="application/rss+xml" href="rss/" title="
12 {% trans 'Feed' %}"/>
11 href="{% static theme_css %}" media="all"/>
12 <link rel="alternate" type="application/rss+xml" href="rss/" title=
13 "{% trans 'Feed' %}"/>
13 14
14 15 <link rel="icon" type="image/png"
15 href="{{ STATIC_URL }}favicon.png">
16 href="{% static 'favicon.png' %}">
16 17
17 18 <meta name="viewport" content="width=device-width, initial-scale=1"/>
18 19 <meta charset="utf-8"/>
20
19 21 {% block head %}{% endblock %}
20 22 </head>
21 23 <body>
22 <script src="{{ STATIC_URL }}js/jquery-2.0.1.min.js"></script>
23 <script src="{{ STATIC_URL }}js/jquery-ui-1.10.3.custom.min.js"></script>
24 <script src="{{ STATIC_URL }}js/jquery.mousewheel.js"></script>
24 <script src="{% static 'js/jquery-2.0.1.min.js' %}"></script>
25 <script src="{% static 'js/jquery-ui-1.10.3.custom.min.js' %}"></script>
26 <script src="{% static 'js/jquery.mousewheel.js' %}"></script>
25 27 <script src="{% url 'django.views.i18n.javascript_catalog' %}"></script>
26 <script src="{{ STATIC_URL }}js/refmaps.js"></script>
27 <script src="{{ STATIC_URL }}js/panel.js"></script>
28 <script src="{{ STATIC_URL }}js/popup.js"></script>
29 <script src="{{ STATIC_URL }}js/image.js"></script>
30 <script src="{{ STATIC_URL }}js/main.js?1"></script>
28 <script src="{% static 'js/refmaps.js' %}"></script>
29 <script src="{% static 'js/panel.js' %}"></script>
30 <script src="{% static 'js/popup.js' %}"></script>
31 <script src="{% static 'js/image.js' %}"></script>
32 <script src="{% static 'js/main.js' %}"></script>
31 33
32 34 <div class="navigation_panel">
33 35 <a class="link" href="{% url 'index' %}">{% trans "All threads" %}</a>
34 36 {% for tag in tags %}
35 37 <a class="tag" href="{% url 'tag' tag_name=tag.name %}"
36 38 >{{ tag.name }}</a>
37 39 {% endfor %}
38 40 <a class="tag" href="{% url 'tags' %}" title="{% trans 'Tag management' %}"
39 41 >[...]</a>
40 42 <a class="link" href="{% url 'settings' %}">{% trans 'Settings' %}</a>
41 43 </div>
42 44
43 45 {% block content %}{% endblock %}
44 46
45 47 <div class="navigation_panel">
46 48 {% block metapanel %}{% endblock %}
47 49 [<a href="{% url "login" %}">{% trans 'Login' %}</a>]
48 50 <a class="link" href="#top">{% trans 'Up' %}</a>
49 51 </div>
50 52
51 53 <div class="footer">
52 54 <!-- Put your banners here -->
53 55 </div>
54 56
55 57 </body>
56 58 </html>
@@ -1,142 +1,143 b''
1 1 {% extends "boards/base.html" %}
2 2
3 3 {% load i18n %}
4 4 {% load markup %}
5 5 {% load cache %}
6 {% load static from staticfiles %}
6 7
7 8 {% block head %}
8 9 <title>Neboard - {{ posts.0.get_title }}</title>
9 10 {% endblock %}
10 11
11 12 {% block content %}
12 13 {% get_current_language as LANGUAGE_CODE %}
13 14
14 <script src="{{ STATIC_URL }}js/thread.js"></script>
15 <script src="{% static 'js/thread.js' }%"></script>
15 16
16 17 {% if posts %}
17 18 {% cache 600 thread_view posts.0.last_edit_time moderator LANGUAGE_CODE %}
18 19 <div class="thread">
19 20 {% for post in posts %}
20 21 {% if bumpable %}
21 22 <div class="post" id="{{ post.id }}">
22 23 {% else %}
23 24 <div class="post dead_post" id="{{ post.id }}">
24 25 {% endif %}
25 26 {% if post.image %}
26 27 <div class="image">
27 28 <a
28 29 class="thumb"
29 30 href="{{ post.image.url }}"><img
30 31 src="{{ post.image.url_200x150 }}"
31 32 alt="{{ post.id }}"
32 33 data-width="{{ post.image_width }}"
33 34 data-height="{{ post.image_height }}"/>
34 35 </a>
35 36 </div>
36 37 {% endif %}
37 38 <div class="message">
38 39 <div class="post-info">
39 40 <span class="title">{{ post.title }}</span>
40 41 <a class="post_id" href="#{{ post.id }}">
41 42 (#{{ post.id }})</a>
42 43 [{{ post.pub_time }}]
43 44 [<a href="#" onclick="javascript:addQuickReply('{{ post.id }}')
44 45 ; return false;">&gt;&gt;</a>]
45 46
46 47 {% if moderator %}
47 48 <span class="moderator_info">
48 49 [<a href="{% url 'delete' post_id=post.id %}"
49 50 >{% trans 'Delete' %}</a>]
50 51 ({{ post.poster_ip }})
51 52 [<a href="{% url 'ban' post_id=post.id %}?next={{ request.path }}"
52 53 >{% trans 'Ban IP' %}</a>]
53 54 </span>
54 55 {% endif %}
55 56 </div>
56 57 {% autoescape off %}
57 58 {{ post.text.rendered }}
58 59 {% endautoescape %}
59 60 </div>
60 61 {% if post.id == posts.0.id %}
61 62 <div class="metadata">
62 63 <span class="tags">{% trans 'Tags' %}:
63 64 {% for tag in post.tags.all %}
64 65 <a class="tag" href="{% url 'tag' tag.name %}">
65 66 {{ tag.name }}</a>
66 67 {% endfor %}
67 68 </span>
68 69 </div>
69 70 {% endif %}
70 71 </div>
71 72 {% endfor %}
72 73 </div>
73 74 {% endcache %}
74 75 {% endif %}
75 76
76 77 <form id="form" enctype="multipart/form-data" method="post"
77 78 >{% csrf_token %}
78 79 <div class="post-form-w">
79 80 <div class="form-title">{% trans "Reply to thread" %} #{{ posts.0.id }}</div>
80 81 <div class="post-form">
81 82 <div class="form-row">
82 83 <div class="form-label">{% trans 'Title' %}</div>
83 84 <div class="form-input">{{ form.title }}</div>
84 85 <div class="form-errors">{{ form.title.errors }}</div>
85 86 </div>
86 87 <div class="form-row">
87 88 <div class="form-label">{% trans 'Formatting' %}</div>
88 89 <div class="form-input" id="mark_panel">
89 90 <span class="mark_btn" id="quote"><span class="quote">&gt;{% trans 'quote' %}</span></span>
90 91 <span class="mark_btn" id="italic"><i>{% trans 'italic' %}</i></span>
91 92 <span class="mark_btn" id="bold"><b>{% trans 'bold' %}</b></span>
92 93 <span class="mark_btn" id="spoiler"><span class="spoiler">{% trans 'spoiler' %}</span></span>
93 94 <span class="mark_btn" id="comment"><span class="comment">// {% trans 'comment' %}</span></span>
94 95 </div>
95 96 </div>
96 97 <div class="form-row">
97 98 <div class="form-label">{% trans 'Text' %}</div>
98 99 <div class="form-input">{{ form.text }}</div>
99 100 <div class="form-errors">{{ form.text.errors }}</div>
100 101 </div>
101 102 <div class="form-row">
102 103 <div class="form-label">{% trans 'Image' %}</div>
103 104 <div class="form-input">{{ form.image }}</div>
104 105 <div class="form-errors">{{ form.image.errors }}</div>
105 106 </div>
106 107 <div class="form-row form-email">
107 108 <div class="form-label">{% trans 'e-mail' %}</div>
108 109 <div class="form-input">{{ form.email }}</div>
109 110 <div class="form-errors">{{ form.email.errors }}</div>
110 111 </div>
111 112 <div class="form-row">
112 113 {{ form.captcha }}
113 114 <div class="form-errors">{{ form.captcha.errors }}</div>
114 115 </div>
115 116 <div class="form-row">
116 117 <div class="form-errors">{{ form.other.errors }}</div>
117 118 </div>
118 119 </div>
119 120
120 121 <div class="form-submit"><input type="submit"
121 122 value="{% trans "Post" %}"/></div>
122 123 <div><a href="{% url "staticpage" name="help" %}">
123 124 {% trans 'Text syntax' %}</a></div>
124 125 </div>
125 126 </form>
126 127
127 128 {% endblock %}
128 129
129 130 {% block metapanel %}
130 131
131 132 {% get_current_language as LANGUAGE_CODE %}
132 133
133 134 <span class="metapanel">
134 135 {% cache 600 thread_meta posts.0.last_edit_time moderator LANGUAGE_CODE %}
135 136 {{ posts.0.get_reply_count }} {% trans 'replies' %},
136 137 {{ posts.0.get_images_count }} {% trans 'images' %}.
137 138 {% trans 'Last update: ' %}{{ posts.0.last_edit_time }}
138 139 [<a href="rss/">RSS</a>]
139 140 {% endcache %}
140 141 </span>
141 142
142 143 {% endblock %}
@@ -1,416 +1,419 b''
1 1 import hashlib
2 2 import string
3 3 from django.core import serializers
4 4 from django.core.urlresolvers import reverse
5 5 from django.http import HttpResponseRedirect
6 6 from django.http.response import HttpResponse
7 7 from django.template import RequestContext
8 8 from django.shortcuts import render, redirect, get_object_or_404
9 9 from django.utils import timezone
10 10
11 11 from boards import forms
12 12 import boards
13 13 from boards import utils
14 14 from boards.forms import ThreadForm, PostForm, SettingsForm, PlainErrorList, \
15 15 ThreadCaptchaForm, PostCaptchaForm, LoginForm, ModeratorSettingsForm
16 16
17 17 from boards.models import Post, Tag, Ban, User, RANK_USER, SETTING_MODERATE
18 18 from boards import authors
19 19 from boards.utils import get_client_ip
20 20 import neboard
21 21
22 22
23 23 def index(request, page=0):
24 24 context = _init_default_context(request)
25 25
26 26 if utils.need_include_captcha(request):
27 27 threadFormClass = ThreadCaptchaForm
28 28 kwargs = {'request': request}
29 29 else:
30 30 threadFormClass = ThreadForm
31 31 kwargs = {}
32 32
33 33 if request.method == 'POST':
34 34 form = threadFormClass(request.POST, request.FILES,
35 35 error_class=PlainErrorList, **kwargs)
36 36 form.session = request.session
37 37
38 38 if form.is_valid():
39 39 return _new_post(request, form)
40 40 else:
41 41 form = threadFormClass(error_class=PlainErrorList, **kwargs)
42 42
43 43 threads = []
44 44 for thread in Post.objects.get_threads(page=int(page)):
45 45 threads.append({'thread': thread,
46 46 'bumpable': thread.can_bump()})
47 47
48 48 context['threads'] = None if len(threads) == 0 else threads
49 49 context['form'] = form
50 50 context['pages'] = range(Post.objects.get_thread_page_count())
51 51
52 52 return render(request, 'boards/posting_general.html',
53 53 context)
54 54
55 55
56 56 def _new_post(request, form, thread_id=boards.models.NO_PARENT):
57 57 """Add a new post (in thread or as a reply)."""
58 58
59 59 ip = get_client_ip(request)
60 60 is_banned = Ban.objects.filter(ip=ip).exists()
61 61
62 62 if is_banned:
63 63 return redirect(you_are_banned)
64 64
65 65 data = form.cleaned_data
66 66
67 67 title = data['title']
68 68 text = data['text']
69 69
70 70 if 'image' in data.keys():
71 71 image = data['image']
72 72 else:
73 73 image = None
74 74
75 75 tags = []
76 76
77 77 new_thread = thread_id == boards.models.NO_PARENT
78 78 if new_thread:
79 79 tag_strings = data['tags']
80 80
81 81 if tag_strings:
82 82 tag_strings = tag_strings.split(' ')
83 83 for tag_name in tag_strings:
84 84 tag_name = string.lower(tag_name.strip())
85 85 if len(tag_name) > 0:
86 86 tag, created = Tag.objects.get_or_create(name=tag_name)
87 87 tags.append(tag)
88 88
89 89 op = None if thread_id == boards.models.NO_PARENT else \
90 90 get_object_or_404(Post, id=thread_id)
91 91 post = Post.objects.create_post(title=title, text=text, ip=ip,
92 92 thread=op, image=image,
93 93 tags=tags, user=_get_user(request))
94 94
95 95 thread_to_show = (post.id if new_thread else thread_id)
96 96
97 97 if new_thread:
98 98 return redirect(thread, post_id=thread_to_show)
99 99 else:
100 100 return redirect(reverse(thread, kwargs={'post_id': thread_to_show}) +
101 101 '#' + str(post.id))
102 102
103 103
104 104 def tag(request, tag_name, page=0):
105 105 """Get all tag threads (posts without a parent)."""
106 106
107 107 tag = get_object_or_404(Tag, name=tag_name)
108 108 threads = []
109 109 for thread in Post.objects.get_threads(tag=tag, page=int(page)):
110 110 threads.append({'thread': thread,
111 111 'bumpable': thread.can_bump()})
112 112
113 113 if request.method == 'POST':
114 114 form = ThreadForm(request.POST, request.FILES,
115 115 error_class=PlainErrorList)
116 116 if form.is_valid():
117 117 return _new_post(request, form)
118 118 else:
119 119 form = forms.ThreadForm(initial={'tags': tag_name},
120 120 error_class=PlainErrorList)
121 121
122 122 context = _init_default_context(request)
123 123 context['threads'] = None if len(threads) == 0 else threads
124 124 context['tag'] = tag
125 125 context['pages'] = range(Post.objects.get_thread_page_count(tag=tag))
126 126
127 127 context['form'] = form
128 128
129 129 return render(request, 'boards/posting_general.html',
130 130 context)
131 131
132 132
133 133 def thread(request, post_id):
134 134 """Get all thread posts"""
135 135
136 136 if utils.need_include_captcha(request):
137 137 postFormClass = PostCaptchaForm
138 138 kwargs = {'request': request}
139 139 else:
140 140 postFormClass = PostForm
141 141 kwargs = {}
142 142
143 143 if request.method == 'POST':
144 144 form = postFormClass(request.POST, request.FILES,
145 145 error_class=PlainErrorList, **kwargs)
146 146 form.session = request.session
147 147
148 148 if form.is_valid():
149 149 return _new_post(request, form, post_id)
150 150 else:
151 151 form = postFormClass(error_class=PlainErrorList, **kwargs)
152 152
153 153 posts = Post.objects.get_thread(post_id)
154 154
155 155 context = _init_default_context(request)
156 156
157 157 context['posts'] = posts
158 158 context['form'] = form
159 159 context['bumpable'] = posts[0].can_bump()
160 160
161 161 return render(request, 'boards/thread.html', context)
162 162
163 163
164 164 def login(request):
165 165 """Log in with user id"""
166 166
167 167 context = _init_default_context(request)
168 168
169 169 if request.method == 'POST':
170 170 form = LoginForm(request.POST, request.FILES,
171 171 error_class=PlainErrorList)
172 172 form.session = request.session
173 173
174 174 if form.is_valid():
175 175 user = User.objects.get(user_id=form.cleaned_data['user_id'])
176 176 request.session['user_id'] = user.id
177 177 return redirect(index)
178 178
179 179 else:
180 180 form = LoginForm()
181 181
182 182 context['form'] = form
183 183
184 184 return render(request, 'boards/login.html', context)
185 185
186 186
187 187 def settings(request):
188 188 """User's settings"""
189 189
190 190 context = _init_default_context(request)
191 191 user = _get_user(request)
192 192 is_moderator = user.is_moderator()
193 193
194 194 if request.method == 'POST':
195 195 if is_moderator:
196 196 form = ModeratorSettingsForm(request.POST,
197 197 error_class=PlainErrorList)
198 198 else:
199 199 form = SettingsForm(request.POST, error_class=PlainErrorList)
200 200
201 201 if form.is_valid():
202 202 selected_theme = form.cleaned_data['theme']
203 203
204 204 user.save_setting('theme', selected_theme)
205 205
206 206 if is_moderator:
207 207 moderate = form.cleaned_data['moderate']
208 208 user.save_setting(SETTING_MODERATE, moderate)
209 209
210 210 return redirect(settings)
211 211 else:
212 212 selected_theme = _get_theme(request)
213 213
214 214 if is_moderator:
215 215 form = ModeratorSettingsForm(initial={'theme': selected_theme,
216 216 'moderate': context['moderator']},
217 217 error_class=PlainErrorList)
218 218 else:
219 219 form = SettingsForm(initial={'theme': selected_theme},
220 220 error_class=PlainErrorList)
221 221
222 222 context['form'] = form
223 223
224 224 return render(request, 'boards/settings.html', context)
225 225
226 226
227 227 def all_tags(request):
228 228 """All tags list"""
229 229
230 230 context = _init_default_context(request)
231 231 context['all_tags'] = Tag.objects.get_not_empty_tags()
232 232
233 233 return render(request, 'boards/tags.html', context)
234 234
235 235
236 236 def jump_to_post(request, post_id):
237 237 """Determine thread in which the requested post is and open it's page"""
238 238
239 239 post = get_object_or_404(Post, id=post_id)
240 240
241 241 if not post.thread:
242 242 return redirect(thread, post_id=post.id)
243 243 else:
244 244 return redirect(reverse(thread, kwargs={'post_id': post.thread.id})
245 245 + '#' + str(post.id))
246 246
247 247
248 248 def authors(request):
249 249 """Show authors list"""
250 250
251 251 context = _init_default_context(request)
252 252 context['authors'] = boards.authors.authors
253 253
254 254 return render(request, 'boards/authors.html', context)
255 255
256 256
257 257 def delete(request, post_id):
258 258 """Delete post"""
259 259
260 260 user = _get_user(request)
261 261 post = get_object_or_404(Post, id=post_id)
262 262
263 263 if user.is_moderator():
264 264 # TODO Show confirmation page before deletion
265 265 Post.objects.delete_post(post)
266 266
267 267 if not post.thread:
268 268 return _redirect_to_next(request)
269 269 else:
270 270 return redirect(thread, post_id=post.thread.id)
271 271
272 272
273 273 def ban(request, post_id):
274 274 """Ban user"""
275 275
276 276 user = _get_user(request)
277 277 post = get_object_or_404(Post, id=post_id)
278 278
279 279 if user.is_moderator():
280 280 # TODO Show confirmation page before ban
281 281 Ban.objects.get_or_create(ip=post.poster_ip)
282 282
283 283 return _redirect_to_next(request)
284 284
285 285
286 286 def you_are_banned(request):
287 287 """Show the page that notifies that user is banned"""
288 288
289 289 context = _init_default_context(request)
290 290 return render(request, 'boards/staticpages/banned.html', context)
291 291
292 292
293 293 def page_404(request):
294 294 """Show page 404 (not found error)"""
295 295
296 296 context = _init_default_context(request)
297 297 return render(request, 'boards/404.html', context)
298 298
299 299
300 300 def tag_subscribe(request, tag_name):
301 301 """Add tag to favorites"""
302 302
303 303 user = _get_user(request)
304 304 tag = get_object_or_404(Tag, name=tag_name)
305 305
306 306 if not tag in user.fav_tags.all():
307 307 user.fav_tags.add(tag)
308 308
309 309 return _redirect_to_next(request)
310 310
311 311
312 312 def tag_unsubscribe(request, tag_name):
313 313 """Remove tag from favorites"""
314 314
315 315 user = _get_user(request)
316 316 tag = get_object_or_404(Tag, name=tag_name)
317 317
318 318 if tag in user.fav_tags.all():
319 319 user.fav_tags.remove(tag)
320 320
321 321 return _redirect_to_next(request)
322 322
323 323
324 324 def static_page(request, name):
325 325 """Show a static page that needs only tags list and a CSS"""
326 326
327 327 context = _init_default_context(request)
328 328 return render(request, 'boards/staticpages/' + name + '.html', context)
329 329
330 330
331 331 def api_get_post(request, post_id):
332 332 """
333 333 Get the JSON of a post. This can be
334 334 used as and API for external clients.
335 335 """
336 336
337 337 post = get_object_or_404(Post, id=post_id)
338 338
339 339 json = serializers.serialize("json", [post], fields=(
340 340 "pub_time", "_text_rendered", "title", "text", "image",
341 341 "image_width", "image_height", "replies", "tags"
342 342 ))
343 343
344 344 return HttpResponse(content=json)
345 345
346 346
347 347 def get_post(request, post_id):
348 348 """ Get the html of a post. Used for popups. """
349 349
350 350 post = get_object_or_404(Post, id=post_id)
351 351
352 352 context = RequestContext(request)
353 353 context["post"] = post
354 354
355 355 return render(request, 'boards/post.html', context)
356 356
357 357
358 358 def _get_theme(request, user=None):
359 359 """Get user's CSS theme"""
360 360
361 361 if not user:
362 362 user = _get_user(request)
363 363 theme = user.get_setting('theme')
364 364 if not theme:
365 365 theme = neboard.settings.DEFAULT_THEME
366 366
367 367 return theme
368 368
369 369
370 370 def _init_default_context(request):
371 371 """Create context with default values that are used in most views"""
372 372
373 373 context = RequestContext(request)
374 374
375 375 user = _get_user(request)
376 376 context['user'] = user
377 377 context['tags'] = user.get_sorted_fav_tags()
378 context['theme'] = _get_theme(request, user)
378
379 theme = _get_theme(request, user)
380 context['theme'] = theme
381 context['theme_css'] = 'css/' + theme + '/base_page.css'
379 382
380 383 moderate = user.get_setting(SETTING_MODERATE)
381 384 if moderate == 'True':
382 385 context['moderator'] = user.is_moderator()
383 386 else:
384 387 context['moderator'] = False
385 388
386 389 return context
387 390
388 391
389 392 def _get_user(request):
390 393 """Get current user from the session"""
391 394
392 395 session = request.session
393 396 if not 'user_id' in session:
394 397 request.session.save()
395 398
396 399 md5 = hashlib.md5()
397 400 md5.update(session.session_key)
398 401 new_id = md5.hexdigest()
399 402
400 403 time_now = timezone.now()
401 404 user = User.objects.create(user_id=new_id, rank=RANK_USER,
402 405 registration_time=time_now)
403 406
404 407 session['user_id'] = user.id
405 408 else:
406 409 user = User.objects.get(id=session['user_id'])
407 410
408 411 return user
409 412
410 413
411 414 def _redirect_to_next(request):
412 415 if 'next' in request.GET:
413 416 next_page = request.GET['next']
414 417 return HttpResponseRedirect(next_page)
415 418 else:
416 419 return redirect(index)
General Comments 0
You need to be logged in to leave comments. Login now