##// END OF EJS Templates
Added subscription to tags.
neko259 -
r145:713a01fa 1.1
parent child Browse files
Show More
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
@@ -1,218 +1,233 b''
1 # SOME DESCRIPTIVE TITLE.
1 # SOME DESCRIPTIVE TITLE.
2 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
2 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3 # This file is distributed under the same license as the PACKAGE package.
3 # This file is distributed under the same license as the PACKAGE package.
4 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
4 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
5 #
5 #
6 msgid ""
6 msgid ""
7 msgstr ""
7 msgstr ""
8 "Project-Id-Version: PACKAGE VERSION\n"
8 "Project-Id-Version: PACKAGE VERSION\n"
9 "Report-Msgid-Bugs-To: \n"
9 "Report-Msgid-Bugs-To: \n"
10 "POT-Creation-Date: 2013-09-06 21:49+0300\n"
10 "POT-Creation-Date: 2013-09-07 19:43+0300\n"
11 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
11 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
12 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13 "Language-Team: LANGUAGE <LL@li.org>\n"
13 "Language-Team: LANGUAGE <LL@li.org>\n"
14 "Language: ru\n"
14 "Language: ru\n"
15 "MIME-Version: 1.0\n"
15 "MIME-Version: 1.0\n"
16 "Content-Type: text/plain; charset=UTF-8\n"
16 "Content-Type: text/plain; charset=UTF-8\n"
17 "Content-Transfer-Encoding: 8bit\n"
17 "Content-Transfer-Encoding: 8bit\n"
18 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
18 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
19 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
19 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
20
20
21 #: templates/boards/404.html:6
21 #: templates/boards/404.html:6
22 msgid "Not found"
22 msgid "Not found"
23 msgstr "Не найдено"
23 msgstr "Не найдено"
24
24
25 #: templates/boards/404.html:12
25 #: templates/boards/404.html:12
26 msgid "This page does not exist"
26 msgid "This page does not exist"
27 msgstr "Этой страницы не существует"
27 msgstr "Этой страницы не существует"
28
28
29 #: templates/boards/authors.html:6
29 #: templates/boards/authors.html:6
30 msgid "Authors"
30 msgid "Authors"
31 msgstr "Авторы"
31 msgstr "Авторы"
32
32
33 #: templates/boards/authors.html:24
33 #: templates/boards/authors.html:24
34 msgid "Distributed under the"
34 msgid "Distributed under the"
35 msgstr "Распространяется под"
35 msgstr "Распространяется под"
36
36
37 #: templates/boards/authors.html:26
37 #: templates/boards/authors.html:26
38 msgid "license"
38 msgid "license"
39 msgstr "лицензией"
39 msgstr "лицензией"
40
40
41 #: templates/boards/authors.html:28
41 #: templates/boards/authors.html:28
42 msgid "Repository"
42 msgid "Repository"
43 msgstr "Репозиторий"
43 msgstr "Репозиторий"
44
44
45 #: templates/boards/banned.html:6
45 #: templates/boards/banned.html:6
46 msgid "Banned"
46 msgid "Banned"
47 msgstr "Заблокирован"
47 msgstr "Заблокирован"
48
48
49 #: templates/boards/banned.html:11
49 #: templates/boards/banned.html:11
50 msgid "Your IP address has been banned. Contact the administrator"
50 msgid "Your IP address has been banned. Contact the administrator"
51 msgstr "Ваш IP адрес был заблокирован. Свяжитесь с администратором"
51 msgstr "Ваш IP адрес был заблокирован. Свяжитесь с администратором"
52
52
53 #: templates/boards/base.html:12
53 #: templates/boards/base.html:12
54 msgid "Feed"
54 msgid "Feed"
55 msgstr "Лента"
55 msgstr "Лента"
56
56
57 #: templates/boards/base.html:29
57 #: templates/boards/base.html:29
58 msgid "All threads"
58 msgid "All threads"
59 msgstr "Все темы"
59 msgstr "Все темы"
60
60
61 #: templates/boards/base.html:35
61 #: templates/boards/base.html:35
62 msgid "Settings"
62 msgid "Settings"
63 msgstr "Настройки"
63 msgstr "Настройки"
64
64
65 #: templates/boards/base.html:42 templates/boards/login.html:6
65 #: templates/boards/base.html:42 templates/boards/login.html:6
66 #: templates/boards/login.html.py:21
66 #: templates/boards/login.html.py:21
67 msgid "Login"
67 msgid "Login"
68 msgstr "Вход"
68 msgstr "Вход"
69
69
70 #: templates/boards/base.html:43
70 #: templates/boards/base.html:43
71 msgid "Up"
71 msgid "Up"
72 msgstr "Вверх"
72 msgstr "Вверх"
73
73
74 #: templates/boards/login.html:15
74 #: templates/boards/login.html:15
75 msgid "User ID"
75 msgid "User ID"
76 msgstr "ID пользователя"
76 msgstr "ID пользователя"
77
77
78 #: templates/boards/login.html:24
78 #: templates/boards/login.html:24
79 msgid "Insert your user id above"
79 msgid "Insert your user id above"
80 msgstr "Вставьте свой ID пользователя выше"
80 msgstr "Вставьте свой ID пользователя выше"
81
81
82 #: templates/boards/posting_general.html:18
82 #: templates/boards/posting_general.html:18
83 msgid "Tag: "
83 msgid "Tag: "
84 msgstr "Тег: "
84 msgstr "Тег: "
85
85
86 #: templates/boards/posting_general.html:35
86 #: templates/boards/posting_general.html:35
87 #: templates/boards/posting_general.html:89 templates/boards/thread.html:27
87 #: templates/boards/posting_general.html:89 templates/boards/thread.html:27
88 #: templates/boards/rss/post.html:5
88 #: templates/boards/rss/post.html:5
89 msgid "Post image"
89 msgid "Post image"
90 msgstr "Изображение сообщения"
90 msgstr "Изображение сообщения"
91
91
92 #: templates/boards/posting_general.html:48
92 #: templates/boards/posting_general.html:48
93 msgid "Reply"
93 msgid "Reply"
94 msgstr "Ответ"
94 msgstr "Ответ"
95
95
96 #: templates/boards/posting_general.html:54 templates/boards/thread.html:46
96 #: templates/boards/posting_general.html:54 templates/boards/thread.html:46
97 msgid "Delete"
97 msgid "Delete"
98 msgstr "Удалить"
98 msgstr "Удалить"
99
99
100 #: templates/boards/posting_general.html:63 templates/boards/thread.html:113
100 #: templates/boards/posting_general.html:63 templates/boards/thread.html:113
101 msgid "replies"
101 msgid "replies"
102 msgstr "ответов"
102 msgstr "ответов"
103
103
104 #: templates/boards/posting_general.html:64 templates/boards/thread.html:114
104 #: templates/boards/posting_general.html:64 templates/boards/thread.html:114
105 msgid "images"
105 msgid "images"
106 msgstr "изображений"
106 msgstr "изображений"
107
107
108 #: templates/boards/posting_general.html:66
108 #: templates/boards/posting_general.html:66
109 #: templates/boards/posting_general.html:139 templates/boards/thread.html:56
109 #: templates/boards/posting_general.html:139 templates/boards/tags.html:7
110 #: templates/boards/rss/post.html:10
110 #: templates/boards/thread.html:56 templates/boards/rss/post.html:10
111 msgid "Tags"
111 msgid "Tags"
112 msgstr "Теги"
112 msgstr "Теги"
113
113
114 #: templates/boards/posting_general.html:115
114 #: templates/boards/posting_general.html:115
115 msgid "No threads exist. Create the first one!"
115 msgid "No threads exist. Create the first one!"
116 msgstr "Нет тем. Создайте первую!"
116 msgstr "Нет тем. Создайте первую!"
117
117
118 #: templates/boards/posting_general.html:121
118 #: templates/boards/posting_general.html:121
119 msgid "Create new thread"
119 msgid "Create new thread"
120 msgstr "Создать новую тему"
120 msgstr "Создать новую тему"
121
121
122 #: templates/boards/posting_general.html:124 templates/boards/thread.html:75
122 #: templates/boards/posting_general.html:124 templates/boards/thread.html:75
123 msgid "Title"
123 msgid "Title"
124 msgstr "Заголовок"
124 msgstr "Заголовок"
125
125
126 #: templates/boards/posting_general.html:129 templates/boards/thread.html:80
126 #: templates/boards/posting_general.html:129 templates/boards/thread.html:80
127 msgid "Text"
127 msgid "Text"
128 msgstr "Текст"
128 msgstr "Текст"
129
129
130 #: templates/boards/posting_general.html:134 templates/boards/thread.html:85
130 #: templates/boards/posting_general.html:134 templates/boards/thread.html:85
131 msgid "Image"
131 msgid "Image"
132 msgstr "Изображение"
132 msgstr "Изображение"
133
133
134 #: templates/boards/posting_general.html:149 templates/boards/thread.html:96
134 #: templates/boards/posting_general.html:149 templates/boards/thread.html:96
135 msgid "Post"
135 msgid "Post"
136 msgstr "Отправить"
136 msgstr "Отправить"
137
137
138 #: templates/boards/posting_general.html:151
138 #: templates/boards/posting_general.html:151
139 msgid "Tags must be delimited by spaces. Text or image is required."
139 msgid "Tags must be delimited by spaces. Text or image is required."
140 msgstr ""
140 msgstr ""
141 "Теги должны быть разделены пробелами. Текст или изображение обязательны."
141 "Теги должны быть разделены пробелами. Текст или изображение обязательны."
142
142
143 #: templates/boards/posting_general.html:154 templates/boards/thread.html:98
143 #: templates/boards/posting_general.html:154 templates/boards/thread.html:98
144 msgid "Basic markdown syntax."
144 msgid "Basic markdown syntax."
145 msgstr "Базовый синтаксис markdown."
145 msgstr "Базовый синтаксис markdown."
146
146
147 #: templates/boards/posting_general.html:164
147 #: templates/boards/posting_general.html:164
148 msgid "Pages:"
148 msgid "Pages:"
149 msgstr "Страницы: "
149 msgstr "Страницы: "
150
150
151 #: templates/boards/settings.html:12
151 #: templates/boards/settings.html:12
152 msgid "User:"
152 msgid "User:"
153 msgstr "Пользователь:"
153 msgstr "Пользователь:"
154
154
155 #: templates/boards/settings.html:14
155 #: templates/boards/settings.html:14
156 msgid "You are moderator."
156 msgid "You are moderator."
157 msgstr "Вы модератор."
157 msgstr "Вы модератор."
158
158
159 #: templates/boards/settings.html:20
159 #: templates/boards/settings.html:20
160 msgid "Theme"
160 msgid "Theme"
161 msgstr "Тема"
161 msgstr "Тема"
162
162
163 #: templates/boards/settings.html:36
163 #: templates/boards/settings.html:36
164 msgid "Save"
164 msgid "Save"
165 msgstr "Сохранить"
165 msgstr "Сохранить"
166
166
167 #: templates/boards/tags.html:7
167 #: templates/boards/tags.html:17
168 msgid "tags"
168 msgid "threads"
169 msgstr "тегов"
169 msgstr "тем"
170
171 #: templates/boards/tags.html:20
172 msgid "Remove"
173 msgstr "Удалить"
174
175 #: templates/boards/tags.html:23
176 msgid "Add"
177 msgstr "Добавить"
178
179 #: templates/boards/tags.html:28
180 msgid "No tags found."
181 msgstr "Теги не найдены."
170
182
171 #: templates/boards/thread.html:72
183 #: templates/boards/thread.html:72
172 msgid "Reply to thread"
184 msgid "Reply to thread"
173 msgstr "Ответить в тему"
185 msgstr "Ответить в тему"
174
186
175 #: templates/boards/thread.html:99
187 #: templates/boards/thread.html:99
176 msgid "Example: "
188 msgid "Example: "
177 msgstr "Пример: "
189 msgstr "Пример: "
178
190
179 #: templates/boards/thread.html:99
191 #: templates/boards/thread.html:99
180 msgid "italic"
192 msgid "italic"
181 msgstr "курсив"
193 msgstr "курсив"
182
194
183 #: templates/boards/thread.html:100
195 #: templates/boards/thread.html:100
184 msgid "bold"
196 msgid "bold"
185 msgstr "полужирный"
197 msgstr "полужирный"
186
198
187 #: templates/boards/thread.html:101
199 #: templates/boards/thread.html:101
188 msgid "Quotes can be inserted with"
200 msgid "Quotes can be inserted with"
189 msgstr "Цитаты могут быть вставлены при помощи"
201 msgstr "Цитаты могут быть вставлены при помощи"
190
202
191 #: templates/boards/thread.html:102
203 #: templates/boards/thread.html:102
192 msgid "Links to answers can be inserted with"
204 msgid "Links to answers can be inserted with"
193 msgstr "Ссылки на ответы могут быть вставлены с помощью"
205 msgstr "Ссылки на ответы могут быть вставлены с помощью"
194
206
195 #: templates/boards/thread.html:115
207 #: templates/boards/thread.html:115
196 msgid "Last update: "
208 msgid "Last update: "
197 msgstr "Последнее обновление: "
209 msgstr "Последнее обновление: "
198
210
211 #~ msgid "tags"
212 #~ msgstr "тегов"
213
199 #~ msgid "Get!"
214 #~ msgid "Get!"
200 #~ msgstr "Гет!"
215 #~ msgstr "Гет!"
201
216
202 #~ msgid "View"
217 #~ msgid "View"
203 #~ msgstr "Просмотр"
218 #~ msgstr "Просмотр"
204
219
205 #~ msgid "gets"
220 #~ msgid "gets"
206 #~ msgstr "гетов"
221 #~ msgstr "гетов"
207
222
208 #~ msgid "author"
223 #~ msgid "author"
209 #~ msgstr "автор"
224 #~ msgstr "автор"
210
225
211 #~ msgid "developer"
226 #~ msgid "developer"
212 #~ msgstr "разработчик"
227 #~ msgstr "разработчик"
213
228
214 #~ msgid "javascript developer"
229 #~ msgid "javascript developer"
215 #~ msgstr "разработчик javascript"
230 #~ msgstr "разработчик javascript"
216
231
217 #~ msgid "designer"
232 #~ msgid "designer"
218 #~ msgstr "дизайнер"
233 #~ msgstr "дизайнер"
@@ -1,47 +1,47 b''
1 {% load staticfiles %}
1 {% load staticfiles %}
2 {% load i18n %}
2 {% load i18n %}
3
3
4 <!DOCTYPE html>
4 <!DOCTYPE html>
5 <html>
5 <html>
6 <head>
6 <head>
7 <link rel="stylesheet" type="text/css"
7 <link rel="stylesheet" type="text/css"
8 href="{{ STATIC_URL }}css/jquery.fancybox.css" media="all"/>
8 href="{{ STATIC_URL }}css/jquery.fancybox.css" media="all"/>
9 <link rel="stylesheet" type="text/css"
9 <link rel="stylesheet" type="text/css"
10 href="{{ STATIC_URL }}css/{{ theme }}/base_page.css" media="all"/>
10 href="{{ STATIC_URL }}css/{{ theme }}/base_page.css" media="all"/>
11 <link rel="alternate" type="application/rss+xml" href="rss/" title="
11 <link rel="alternate" type="application/rss+xml" href="rss/" title="
12 {% trans 'Feed' %}"/>
12 {% trans 'Feed' %}"/>
13
13
14 <link rel="icon" type="image/png"
14 <link rel="icon" type="image/png"
15 href="{{ STATIC_URL }}favicon.png">
15 href="{{ STATIC_URL }}favicon.png">
16
16
17 <meta name="viewport" content="width=device-width, initial-scale=1"/>
17 <meta name="viewport" content="width=device-width, initial-scale=1"/>
18 <meta charset="utf-8"/>
18 <meta charset="utf-8"/>
19 {% block head %}{% endblock %}
19 {% block head %}{% endblock %}
20 </head>
20 </head>
21 <body>
21 <body>
22 <script src="{{ STATIC_URL }}js/jquery-2.0.1.min.js"></script>
22 <script src="{{ STATIC_URL }}js/jquery-2.0.1.min.js"></script>
23 <script src="{{ STATIC_URL }}js/jquery.fancybox.pack.js"></script>
23 <script src="{{ STATIC_URL }}js/jquery.fancybox.pack.js"></script>
24 <script src="{% url 'django.views.i18n.javascript_catalog' %}"></script>
24 <script src="{% url 'django.views.i18n.javascript_catalog' %}"></script>
25 <script src="{{ STATIC_URL }}js/refmaps.js"></script>
25 <script src="{{ STATIC_URL }}js/refmaps.js"></script>
26 <script src="{{ STATIC_URL }}js/main.js"></script>
26 <script src="{{ STATIC_URL }}js/main.js"></script>
27
27
28 <div class="navigation_panel">
28 <div class="navigation_panel">
29 <a class="link" href="{% url 'index' %}">{% trans "All threads" %}</a>
29 <a class="link" href="{% url 'index' %}">{% trans "All threads" %}</a>
30 {% for tag in tags %}
30 {% for tag in tags %}
31 <a class="tag" href="{% url 'tag' tag_name=tag.name %}">
31 <a class="tag" href="{% url 'tag' tag_name=tag.name %}">
32 {{ tag.name }}</a>({{ tag.get_post_count }})
32 {{ tag.name }}</a>
33 {% endfor %}
33 {% endfor %}
34 <a class="tag" href="{% url 'tags' %}">[...]</a>
34 <a class="tag" href="{% url 'tags' %}">[...]</a>
35 <a class="link" href="{% url 'settings' %}">{% trans 'Settings' %}</a>
35 <a class="link" href="{% url 'settings' %}">{% trans 'Settings' %}</a>
36 </div>
36 </div>
37
37
38 {% block content %}{% endblock %}
38 {% block content %}{% endblock %}
39
39
40 <div class="navigation_panel">
40 <div class="navigation_panel">
41 {% block metapanel %}{% endblock %}
41 {% block metapanel %}{% endblock %}
42 [<a href="{% url "login" %}">{% trans 'Login' %}</a>]
42 [<a href="{% url "login" %}">{% trans 'Login' %}</a>]
43 <a class="link" href="#top">{% trans 'Up' %}</a>
43 <a class="link" href="#top">{% trans 'Up' %}</a>
44 </div>
44 </div>
45
45
46 </body>
46 </body>
47 </html>
47 </html>
@@ -1,24 +1,32 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 <title>Neboard - {% trans "tags" %}</title>
7 <title>Neboard - {% trans "Tags" %}</title>
8 {% endblock %}
8 {% endblock %}
9
9
10 {% block content %}
10 {% block content %}
11
11
12 <div class="post">
12 <div class="post">
13 {% if tags %}
13 {% if all_tags %}
14 {% for tag in all_tags %}
14 {% for tag in all_tags %}
15 <a class="tag" href="{% url 'tag' tag.name %}">
15 <a class="tag" href="{% url 'tag' tag.name %}">
16 {{ tag.name }}</a><br />
16 {{ tag.name }}</a>
17 ({{ tag.get_post_count }} {% trans 'threads' %})
18 {% if tag in user.fav_tags.all %}
19 [<a href="{% url 'tag_unsubscribe' tag.name %}"
20 >{% trans 'Remove' %}</a>]
21 {% else %}
22 [<a href="{% url 'tag_subscribe' tag.name %}"
23 >{% trans 'Add' %}</a>]
24 {% endif %}
25 <br />
17 {% endfor %}
26 {% endfor %}
18 {% else %}
27 {% else %}
19 No tags found.
28 {% trans 'No tags found.' %}
20 <hr />
21 {% endif %}
29 {% endif %}
22 </div>
30 </div>
23
31
24 {% endblock %} No newline at end of file
32 {% endblock %}
@@ -1,42 +1,50 b''
1 from django.conf.urls import patterns, url, include
1 from django.conf.urls import patterns, url, include
2 from boards import views
2 from boards import views
3 from boards.rss import AllThreadsFeed, TagThreadsFeed, ThreadPostsFeed
3 from boards.rss import AllThreadsFeed, TagThreadsFeed, ThreadPostsFeed
4
4
5 js_info_dict = {
5 js_info_dict = {
6 'packages': ('boards',),
6 'packages': ('boards',),
7 }
7 }
8
8
9 urlpatterns = patterns('',
9 urlpatterns = patterns('',
10
10
11 # /boards/
11 # /boards/
12 url(r'^$', views.index, name='index'),
12 url(r'^$', views.index, name='index'),
13 # /boards/page/
13 # /boards/page/
14 url(r'^page/(?P<page>\w+)/$', views.index, name='index'),
14 url(r'^page/(?P<page>\w+)/$', views.index, name='index'),
15
15
16 # login page
16 # login page
17 url(r'^login/$', views.login, name='login'),
17 url(r'^login/$', views.login, name='login'),
18
18
19 # /boards/tag/tag_name/
19 # /boards/tag/tag_name/
20 url(r'^tag/(?P<tag_name>\w+)/$', views.tag, name='tag'),
20 url(r'^tag/(?P<tag_name>\w+)/$', views.tag, name='tag'),
21 # /boards/tag/tag_id/page/
21 # /boards/tag/tag_id/page/
22 url(r'^tag/(?P<tag_name>\w+)/page/(?P<page>\w+)/$', views.tag, name='tag'),
22 url(r'^tag/(?P<tag_name>\w+)/page/(?P<page>\w+)/$', views.tag, name='tag'),
23
24 # /boards/tag/tag_name/unsubscribe/
25 url(r'^tag/(?P<tag_name>\w+)/subscribe/$', views.tag_subscribe,
26 name='tag_subscribe'),
27 # /boards/tag/tag_name/unsubscribe/
28 url(r'^tag/(?P<tag_name>\w+)/unsubscribe/$', views.tag_unsubscribe,
29 name='tag_unsubscribe'),
30
23 # /boards/thread/
31 # /boards/thread/
24 url(r'^thread/(?P<post_id>\w+)/$', views.thread, name='thread'),
32 url(r'^thread/(?P<post_id>\w+)/$', views.thread, name='thread'),
25 # /boards/theme/theme_name/
33 # /boards/theme/theme_name/
26 url(r'^settings/$', views.settings, name='settings'),
34 url(r'^settings/$', views.settings, name='settings'),
27 url(r'^tags/$', views.all_tags, name='tags'),
35 url(r'^tags/$', views.all_tags, name='tags'),
28 url(r'^captcha/', include('captcha.urls')),
36 url(r'^captcha/', include('captcha.urls')),
29 url(r'^jump/(?P<post_id>\w+)/$', views.jump_to_post, name='jumper'),
37 url(r'^jump/(?P<post_id>\w+)/$', views.jump_to_post, name='jumper'),
30 url(r'^authors/$', views.authors, name='authors'),
38 url(r'^authors/$', views.authors, name='authors'),
31 url(r'^delete/(?P<post_id>\w+)/$', views.delete, name='delete'),
39 url(r'^delete/(?P<post_id>\w+)/$', views.delete, name='delete'),
32 url(r'^banned/$', views.you_are_banned, name='banned'),
40 url(r'^banned/$', views.you_are_banned, name='banned'),
33
41
34 # RSS feeds
42 # RSS feeds
35 url(r'^rss/$', AllThreadsFeed()),
43 url(r'^rss/$', AllThreadsFeed()),
36 url(r'^page/(?P<page>\w+)/rss/$', AllThreadsFeed()),
44 url(r'^page/(?P<page>\w+)/rss/$', AllThreadsFeed()),
37 url(r'^tag/(?P<tag_name>\w+)/rss/$', TagThreadsFeed()),
45 url(r'^tag/(?P<tag_name>\w+)/rss/$', TagThreadsFeed()),
38 url(r'^tag/(?P<tag_name>\w+)/page/(?P<page>\w+)/rss/$', TagThreadsFeed()),
46 url(r'^tag/(?P<tag_name>\w+)/page/(?P<page>\w+)/rss/$', TagThreadsFeed()),
39 url(r'^thread/(?P<post_id>\w+)/rss/$', ThreadPostsFeed()),
47 url(r'^thread/(?P<post_id>\w+)/rss/$', ThreadPostsFeed()),
40
48
41 url(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),
49 url(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),
42 )
50 )
@@ -1,299 +1,320 b''
1 import hashlib
1 import hashlib
2 from django.core.urlresolvers import reverse
2 from django.core.urlresolvers import reverse
3 from django.template import RequestContext
3 from django.template import RequestContext
4 from django.shortcuts import render, redirect, get_object_or_404
4 from django.shortcuts import render, redirect, get_object_or_404
5 from django.http import HttpResponseRedirect
5 from django.http import HttpResponseRedirect
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, RANK_MODERATOR, NO_PARENT
14 from boards.models import Post, Tag, Ban, User, RANK_USER, RANK_MODERATOR, 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
32
33 if form.is_valid():
33 if form.is_valid():
34 return _new_post(request, form)
34 return _new_post(request, form)
35 else:
35 else:
36 form = threadFormClass(error_class=PlainErrorList, **kwargs)
36 form = threadFormClass(error_class=PlainErrorList, **kwargs)
37
37
38 threads = Post.objects.get_threads(page=int(page))
38 threads = Post.objects.get_threads(page=int(page))
39
39
40 context['threads'] = None if len(threads) == 0 else threads
40 context['threads'] = None if len(threads) == 0 else threads
41 context['form'] = form
41 context['form'] = form
42 context['pages'] = range(Post.objects.get_thread_page_count())
42 context['pages'] = range(Post.objects.get_thread_page_count())
43
43
44 return render(request, 'boards/posting_general.html',
44 return render(request, 'boards/posting_general.html',
45 context)
45 context)
46
46
47
47
48 def _new_post(request, form, thread_id=boards.models.NO_PARENT):
48 def _new_post(request, form, thread_id=boards.models.NO_PARENT):
49 """Add a new post (in thread or as a reply)."""
49 """Add a new post (in thread or as a reply)."""
50
50
51 ip = _get_client_ip(request)
51 ip = _get_client_ip(request)
52 is_banned = Ban.objects.filter(ip=ip).count() > 0
52 is_banned = Ban.objects.filter(ip=ip).count() > 0
53
53
54 if is_banned:
54 if is_banned:
55 return redirect(you_are_banned)
55 return redirect(you_are_banned)
56
56
57 data = form.cleaned_data
57 data = form.cleaned_data
58
58
59 title = data['title']
59 title = data['title']
60 text = data['text']
60 text = data['text']
61
61
62 if 'image' in data.keys():
62 if 'image' in data.keys():
63 image = data['image']
63 image = data['image']
64 else:
64 else:
65 image = None
65 image = None
66
66
67 tags = []
67 tags = []
68
68
69 new_thread = thread_id == boards.models.NO_PARENT
69 new_thread = thread_id == boards.models.NO_PARENT
70 if new_thread:
70 if new_thread:
71 tag_strings = data['tags']
71 tag_strings = data['tags']
72
72
73 if tag_strings:
73 if tag_strings:
74 tag_strings = tag_strings.split(' ')
74 tag_strings = tag_strings.split(' ')
75 for tag_name in tag_strings:
75 for tag_name in tag_strings:
76 tag_name = tag_name.strip()
76 tag_name = tag_name.strip()
77 if len(tag_name) > 0:
77 if len(tag_name) > 0:
78 tag, created = Tag.objects.get_or_create(name=tag_name)
78 tag, created = Tag.objects.get_or_create(name=tag_name)
79 tags.append(tag)
79 tags.append(tag)
80
80
81 # TODO Add a possibility to define a link image instead of an image file.
81 # TODO Add a possibility to define a link image instead of an image file.
82 # If a link is given, download the image automatically.
82 # If a link is given, download the image automatically.
83
83
84 post = Post.objects.create_post(title=title, text=text, ip=ip,
84 post = Post.objects.create_post(title=title, text=text, ip=ip,
85 parent_id=thread_id, image=image,
85 parent_id=thread_id, image=image,
86 tags=tags)
86 tags=tags)
87
87
88 thread_to_show = (post.id if new_thread else thread_id)
88 thread_to_show = (post.id if new_thread else thread_id)
89
89
90 if new_thread:
90 if new_thread:
91 return redirect(thread, post_id=thread_to_show)
91 return redirect(thread, post_id=thread_to_show)
92 else:
92 else:
93 return redirect(reverse(thread,
93 return redirect(reverse(thread,
94 kwargs={'post_id': thread_to_show}) + '#'
94 kwargs={'post_id': thread_to_show}) + '#'
95 + str(post.id))
95 + str(post.id))
96
96
97
97
98 def tag(request, tag_name, page=0):
98 def tag(request, tag_name, page=0):
99 """Get all tag threads (posts without a parent)."""
99 """Get all tag threads (posts without a parent)."""
100
100
101 tag = get_object_or_404(Tag, name=tag_name)
101 tag = get_object_or_404(Tag, name=tag_name)
102 threads = Post.objects.get_threads(tag=tag, page=int(page))
102 threads = Post.objects.get_threads(tag=tag, page=int(page))
103
103
104 if request.method == 'POST':
104 if request.method == 'POST':
105 form = ThreadForm(request.POST, request.FILES,
105 form = ThreadForm(request.POST, request.FILES,
106 error_class=PlainErrorList)
106 error_class=PlainErrorList)
107 if form.is_valid():
107 if form.is_valid():
108 return _new_post(request, form)
108 return _new_post(request, form)
109 else:
109 else:
110 form = forms.ThreadForm(initial={'tags': tag_name},
110 form = forms.ThreadForm(initial={'tags': tag_name},
111 error_class=PlainErrorList)
111 error_class=PlainErrorList)
112
112
113 context = _init_default_context(request)
113 context = _init_default_context(request)
114 context['threads'] = None if len(threads) == 0 else threads
114 context['threads'] = None if len(threads) == 0 else threads
115 context['tag'] = tag_name
115 context['tag'] = tag_name
116 context['pages'] = range(Post.objects.get_thread_page_count(tag=tag))
116 context['pages'] = range(Post.objects.get_thread_page_count(tag=tag))
117
117
118 context['form'] = form
118 context['form'] = form
119
119
120 return render(request, 'boards/posting_general.html',
120 return render(request, 'boards/posting_general.html',
121 context)
121 context)
122
122
123
123
124 def thread(request, post_id):
124 def thread(request, post_id):
125 """Get all thread posts"""
125 """Get all thread posts"""
126
126
127 if utils.need_include_captcha(request):
127 if utils.need_include_captcha(request):
128 postFormClass = PostCaptchaForm
128 postFormClass = PostCaptchaForm
129 kwargs = {'request': request}
129 kwargs = {'request': request}
130 else:
130 else:
131 postFormClass = PostForm
131 postFormClass = PostForm
132 kwargs = {}
132 kwargs = {}
133
133
134 if request.method == 'POST':
134 if request.method == 'POST':
135 form = postFormClass(request.POST, request.FILES,
135 form = postFormClass(request.POST, request.FILES,
136 error_class=PlainErrorList, **kwargs)
136 error_class=PlainErrorList, **kwargs)
137 if form.is_valid():
137 if form.is_valid():
138 return _new_post(request, form, post_id)
138 return _new_post(request, form, post_id)
139 else:
139 else:
140 form = postFormClass(error_class=PlainErrorList, **kwargs)
140 form = postFormClass(error_class=PlainErrorList, **kwargs)
141
141
142 posts = Post.objects.get_thread(post_id)
142 posts = Post.objects.get_thread(post_id)
143
143
144 context = _init_default_context(request)
144 context = _init_default_context(request)
145
145
146 context['posts'] = posts
146 context['posts'] = posts
147 context['form'] = form
147 context['form'] = form
148
148
149 return render(request, 'boards/thread.html', context)
149 return render(request, 'boards/thread.html', context)
150
150
151
151
152 def login(request):
152 def login(request):
153 """Log in with user id"""
153 """Log in with user id"""
154
154
155 context = _init_default_context(request)
155 context = _init_default_context(request)
156
156
157 if request.method == 'POST':
157 if request.method == 'POST':
158 form = LoginForm(request.POST, request.FILES, error_class=PlainErrorList)
158 form = LoginForm(request.POST, request.FILES, error_class=PlainErrorList)
159 if form.is_valid():
159 if form.is_valid():
160 user = User.objects.get(user_id=form.cleaned_data['user_id'])
160 user = User.objects.get(user_id=form.cleaned_data['user_id'])
161 request.session['user_id'] = user.id
161 request.session['user_id'] = user.id
162 return redirect(index)
162 return redirect(index)
163
163
164 else:
164 else:
165 form = LoginForm()
165 form = LoginForm()
166
166
167 context['form'] = form
167 context['form'] = form
168
168
169 return render(request, 'boards/login.html', context)
169 return render(request, 'boards/login.html', context)
170
170
171
171
172 def settings(request):
172 def settings(request):
173 """User's settings"""
173 """User's settings"""
174
174
175 context = _init_default_context(request)
175 context = _init_default_context(request)
176
176
177 if request.method == 'POST':
177 if request.method == 'POST':
178 form = SettingsForm(request.POST)
178 form = SettingsForm(request.POST)
179 if form.is_valid():
179 if form.is_valid():
180 selected_theme = form.cleaned_data['theme']
180 selected_theme = form.cleaned_data['theme']
181
181
182 user = _get_user(request)
182 user = _get_user(request)
183 user.save_setting('theme', selected_theme)
183 user.save_setting('theme', selected_theme)
184
184
185 return redirect(settings)
185 return redirect(settings)
186 else:
186 else:
187 selected_theme = _get_theme(request)
187 selected_theme = _get_theme(request)
188 form = SettingsForm(initial={'theme': selected_theme})
188 form = SettingsForm(initial={'theme': selected_theme})
189 context['form'] = form
189 context['form'] = form
190
190
191 return render(request, 'boards/settings.html', context)
191 return render(request, 'boards/settings.html', context)
192
192
193
193
194 def all_tags(request):
194 def all_tags(request):
195 """All tags list"""
195 """All tags list"""
196
196
197 context = _init_default_context(request)
197 context = _init_default_context(request)
198 context['all_tags'] = Tag.objects.get_not_empty_tags()
198 context['all_tags'] = Tag.objects.get_not_empty_tags()
199
199
200 return render(request, 'boards/tags.html', context)
200 return render(request, 'boards/tags.html', context)
201
201
202
202
203 def jump_to_post(request, post_id):
203 def jump_to_post(request, post_id):
204 """Determine thread in which the requested post is and open it's page"""
204 """Determine thread in which the requested post is and open it's page"""
205
205
206 post = get_object_or_404(Post, id=post_id)
206 post = get_object_or_404(Post, id=post_id)
207
207
208 if boards.models.NO_PARENT == post.parent:
208 if boards.models.NO_PARENT == post.parent:
209 return redirect(thread, post_id=post.id)
209 return redirect(thread, post_id=post.id)
210 else:
210 else:
211 parent_thread = get_object_or_404(Post, id=post.parent)
211 parent_thread = get_object_or_404(Post, id=post.parent)
212 return redirect(reverse(thread, kwargs={'post_id': parent_thread.id})
212 return redirect(reverse(thread, kwargs={'post_id': parent_thread.id})
213 + '#' + str(post.id))
213 + '#' + str(post.id))
214
214
215
215
216 def authors(request):
216 def authors(request):
217 context = _init_default_context(request)
217 context = _init_default_context(request)
218 context['authors'] = boards.authors.authors
218 context['authors'] = boards.authors.authors
219
219
220 return render(request, 'boards/authors.html', context)
220 return render(request, 'boards/authors.html', context)
221
221
222
222
223 def delete(request, post_id):
223 def delete(request, post_id):
224 user = _get_user(request)
224 user = _get_user(request)
225 post = get_object_or_404(Post, id=post_id)
225 post = get_object_or_404(Post, id=post_id)
226
226
227 if user.is_moderator():
227 if user.is_moderator():
228 Post.objects.delete_post(post)
228 Post.objects.delete_post(post)
229
229
230 if NO_PARENT == post.parent:
230 if NO_PARENT == post.parent:
231 return redirect(index)
231 return redirect(index)
232 else:
232 else:
233 return redirect(thread, post_id=post.parent)
233 return redirect(thread, post_id=post.parent)
234
234
235
235 def you_are_banned(request):
236 def you_are_banned(request):
236 context = _init_default_context(request)
237 context = _init_default_context(request)
237 return render(request, 'boards/banned.html', context)
238 return render(request, 'boards/banned.html', context)
238
239
239
240
240 def page_404(request):
241 def page_404(request):
241 context = _init_default_context(request)
242 context = _init_default_context(request)
242 return render(request, 'boards/404.html', context)
243 return render(request, 'boards/404.html', context)
243
244
244
245
246 def tag_subscribe(request, tag_name):
247 user = _get_user(request)
248 tag = get_object_or_404(Tag, name=tag_name)
249
250 if not tag in user.fav_tags.all():
251 user.fav_tags.add(tag)
252
253 return redirect(all_tags)
254
255
256 def tag_unsubscribe(request, tag_name):
257 user = _get_user(request)
258 tag = get_object_or_404(Tag, name=tag_name)
259
260 if tag in user.fav_tags.all():
261 user.fav_tags.remove(tag)
262
263 return redirect(all_tags)
264
265
245 def _get_theme(request):
266 def _get_theme(request):
246 """Get user's CSS theme"""
267 """Get user's CSS theme"""
247
268
248 user = _get_user(request)
269 user = _get_user(request)
249 theme = user.get_setting('theme')
270 theme = user.get_setting('theme')
250 if not theme:
271 if not theme:
251 theme = neboard.settings.DEFAULT_THEME
272 theme = neboard.settings.DEFAULT_THEME
252
273
253 return theme
274 return theme
254
275
255
276
256 def _get_client_ip(request):
277 def _get_client_ip(request):
257 x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
278 x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
258 if x_forwarded_for:
279 if x_forwarded_for:
259 ip = x_forwarded_for.split(',')[-1].strip()
280 ip = x_forwarded_for.split(',')[-1].strip()
260 else:
281 else:
261 ip = request.META.get('REMOTE_ADDR')
282 ip = request.META.get('REMOTE_ADDR')
262 return ip
283 return ip
263
284
264
285
265 def _init_default_context(request):
286 def _init_default_context(request):
266 """Create context with default values that are used in most views"""
287 """Create context with default values that are used in most views"""
267
288
268 context = RequestContext(request)
289 context = RequestContext(request)
269 context['tags'] = Tag.objects.get_popular_tags()
290 context['user'] = _get_user(request)
291 context['tags'] = _get_user(request).fav_tags.all()
270 context['theme'] = _get_theme(request)
292 context['theme'] = _get_theme(request)
271 context['user'] = _get_user(request)
272
293
273 return context
294 return context
274
295
275
296
276 def _get_user(request):
297 def _get_user(request):
277 """Get current user from the session"""
298 """Get current user from the session"""
278
299
279 session = request.session
300 session = request.session
280 if not 'user_id' in session:
301 if not 'user_id' in session:
281 request.session.save()
302 request.session.save()
282
303
283 md5 = hashlib.md5()
304 md5 = hashlib.md5()
284 md5.update(session.session_key)
305 md5.update(session.session_key)
285 new_id = md5.hexdigest()
306 new_id = md5.hexdigest()
286
307
287 time_now = timezone.now()
308 time_now = timezone.now()
288 user = User.objects.create(user_id=new_id, rank=RANK_USER,
309 user = User.objects.create(user_id=new_id, rank=RANK_USER,
289 registration_time=time_now,
310 registration_time=time_now,
290 last_access_time=time_now)
311 last_access_time=time_now)
291
312
292 session['user_id'] = user.id
313 session['user_id'] = user.id
293 else:
314 else:
294 user = User.objects.get(id=session['user_id'])
315 user = User.objects.get(id=session['user_id'])
295 user.save()
316 user.save()
296
317
297 user.last_access_time = timezone.now()
318 user.last_access_time = timezone.now()
298
319
299 return user
320 return user
General Comments 0
You need to be logged in to leave comments. Login now