# HG changeset patch # User neko259 # Date 2014-07-12 17:28:31 # Node ID 7c2d35f4b8b290fcf36fa00eabd6ca8b34a829a4 # Parent e387632ece70314e71edccfacde7deb0f03c2868 Removed linked tags. Added changelog for 2.0. Fixed reply connection. diff --git a/boards/admin.py b/boards/admin.py --- a/boards/admin.py +++ b/boards/admin.py @@ -11,9 +11,7 @@ class PostAdmin(admin.ModelAdmin): class TagAdmin(admin.ModelAdmin): - list_display = ('name', 'linked') - list_filter = ('linked',) - + list_display = ('name',) class ThreadAdmin(admin.ModelAdmin): diff --git a/boards/forms.py b/boards/forms.py --- a/boards/forms.py +++ b/boards/forms.py @@ -20,8 +20,7 @@ ATTRIBUTE_PLACEHOLDER = 'placeholder' LAST_POST_TIME = 'last_post_time' LAST_LOGIN_TIME = 'last_login_time' -TEXT_PLACEHOLDER = _('''Type message here. You can reply to message >>123 like - this. 2 new lines are required to start new paragraph.''') +TEXT_PLACEHOLDER = _('''Type message here. Use formatting panel for more advanced usage.''') TAGS_PLACEHOLDER = _('tag1 several_words_tag') ERROR_IMAGE_DUPLICATE = _('Such image was already posted') diff --git a/boards/locale/ru/LC_MESSAGES/django.mo b/boards/locale/ru/LC_MESSAGES/django.mo index a42e184a9643aadad3bd861ca933745555f07f60..97fe3500745f319124b9169de415f3d4297c234c GIT binary patch literal 6392 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\n" "Language-Team: LANGUAGE \n" @@ -35,91 +35,87 @@ msgid "designer" msgstr "дизайнер" #: forms.py:23 -msgid "" -"Type message here. You can reply to message >>123 like\n" -" this. 2 new lines are required to start new paragraph." -msgstr "" -"Введите сообщение здесь. Вы можете ответить на сообщение >>123 вот так. 2 " -"переноса строки обязательны для создания нового абзаца." +msgid "Type message here. Use formatting panel for more advanced usage." +msgstr "Вводите сообщение сюда. Используйте панель для более сложного форматирования." -#: forms.py:25 +#: forms.py:24 msgid "tag1 several_words_tag" msgstr "тег1 тег_из_нескольких_слов" -#: forms.py:27 +#: forms.py:26 msgid "Such image was already posted" msgstr "Такое изображение уже было загружено" -#: forms.py:29 +#: forms.py:28 msgid "Title" msgstr "Заголовок" -#: forms.py:30 +#: forms.py:29 msgid "Text" msgstr "Текст" -#: forms.py:31 +#: forms.py:30 msgid "Tag" msgstr "Тег" -#: forms.py:32 templates/boards/base.html:54 templates/search/search.html:9 +#: forms.py:31 templates/boards/base.html:54 templates/search/search.html:9 #: templates/search/search.html.py:13 msgid "Search" msgstr "Поиск" -#: forms.py:109 +#: forms.py:108 msgid "Image" msgstr "Изображение" -#: forms.py:114 +#: forms.py:113 msgid "e-mail" msgstr "" -#: forms.py:125 +#: forms.py:124 #, python-format msgid "Title must have less than %s characters" msgstr "Заголовок должен иметь меньше %s символов" -#: forms.py:134 +#: forms.py:133 #, python-format msgid "Text must have less than %s characters" msgstr "Текст должен быть короче %s символов" -#: forms.py:145 +#: forms.py:144 #, python-format msgid "Image must be less than %s bytes" msgstr "Изображение должно быть менее %s байт" -#: forms.py:180 +#: forms.py:179 msgid "Either text or image must be entered." msgstr "Текст или картинка должны быть введены." -#: forms.py:200 +#: forms.py:199 #, python-format msgid "Wait %s seconds after last posting" msgstr "Подождите %s секунд после последнего постинга" -#: forms.py:216 templates/boards/tags.html:7 templates/boards/rss/post.html:10 +#: forms.py:215 templates/boards/tags.html:7 templates/boards/rss/post.html:10 msgid "Tags" msgstr "Теги" -#: forms.py:223 forms.py:291 +#: forms.py:222 forms.py:290 msgid "Inappropriate characters in tags." msgstr "Недопустимые символы в тегах." -#: forms.py:251 forms.py:272 +#: forms.py:250 forms.py:271 msgid "Captcha validation failed" msgstr "Проверка капчи провалена" -#: forms.py:278 +#: forms.py:277 msgid "Theme" msgstr "Тема" -#: forms.py:314 +#: forms.py:313 msgid "Invalid master password" msgstr "Неверный мастер-пароль" -#: forms.py:328 +#: forms.py:327 #, python-format msgid "Wait %s minutes after last login" msgstr "Подождите %s минут после последнего входа" @@ -186,7 +182,7 @@ msgstr "Вверх" msgid "Insert your user id above" msgstr "Вставьте свой ID пользователя выше" -#: templates/boards/post.html:21 templates/boards/staticpages/help.html:19 +#: templates/boards/post.html:21 templates/boards/staticpages/help.html:17 msgid "Quote" msgstr "Цитата" @@ -340,33 +336,25 @@ msgid "Syntax" msgstr "Синтаксис" #: templates/boards/staticpages/help.html:11 -msgid "2 line breaks for a new line." -msgstr "2 перевода строки создают новый абзац." - -#: templates/boards/staticpages/help.html:12 msgid "Italic text" msgstr "Курсивный текст" -#: templates/boards/staticpages/help.html:13 +#: templates/boards/staticpages/help.html:12 msgid "Bold text" msgstr "Полужирный текст" -#: templates/boards/staticpages/help.html:14 +#: templates/boards/staticpages/help.html:13 msgid "Spoiler" msgstr "Спойлер" -#: templates/boards/staticpages/help.html:15 +#: templates/boards/staticpages/help.html:14 msgid "Link to a post" msgstr "Ссылка на сообщение" -#: templates/boards/staticpages/help.html:16 +#: templates/boards/staticpages/help.html:15 msgid "Strikethrough text" msgstr "Зачеркнутый текст" -#: templates/boards/staticpages/help.html:17 -msgid "You need to new line before:" -msgstr "Перед этими тегами нужна новая строка:" - -#: templates/boards/staticpages/help.html:18 +#: templates/boards/staticpages/help.html:16 msgid "Comment" msgstr "Комментарий" diff --git a/boards/models/post.py b/boards/models/post.py --- a/boards/models/post.py +++ b/boards/models/post.py @@ -38,13 +38,12 @@ UNKNOWN_UA = '' SETTING_MODERATE = "moderate" -REGEX_REPLY = re.compile('>>(\d+)') +REGEX_REPLY = re.compile(r'>>(\d+)') logger = logging.getLogger(__name__) class PostManager(models.Manager): - def create_post(self, title, text, image=None, thread=None, ip=NO_IP, tags=None): """ @@ -79,13 +78,6 @@ class PostManager(models.Manager): thread.replies.add(post) if tags: - linked_tags = [] - for tag in tags: - tag_linked_tags = tag.get_linked_tags() - if len(tag_linked_tags) > 0: - linked_tags.extend(tag_linked_tags) - - tags.extend(linked_tags) map(thread.add_tag, tags) if new_thread: @@ -128,7 +120,7 @@ class PostManager(models.Manager): Connects replies to a post to show them as a reflink map """ - for reply_number in re.finditer(REGEX_REPLY, post.text.raw): + for reply_number in re.finditer(REGEX_REPLY, post.text.rendered): post_id = reply_number.group(1) ref_post = self.filter(id=post_id) if ref_post.count() > 0: @@ -218,13 +210,18 @@ class Post(models.Model, Viewable): return title def build_refmap(self): + """ + Builds a replies map string from replies list. This is a cache to stop + the server from recalculating the map on every post show. + """ map_string = '' first = True for refpost in self.referenced_posts.all(): if not first: map_string += ', ' - map_string += '>>%s' % (refpost.get_url(), refpost.id) + map_string += '>>%s' % (refpost.get_url(), + refpost.id) first = False self.refmap = map_string @@ -249,10 +246,10 @@ class Post(models.Model, Viewable): thread = self.get_thread() thread.add_tag(tag) self.last_edit_time = edit_time - self.save() + self.save(update_fields=['last_edit_time']) thread.last_edit_time = edit_time - thread.save() + thread.save(update_fields=['last_edit_time']) @transaction.atomic def remove_tag(self, tag): @@ -261,10 +258,10 @@ class Post(models.Model, Viewable): thread = self.get_thread() thread.remove_tag(tag) self.last_edit_time = edit_time - self.save() + self.save(update_fields=['last_edit_time']) thread.last_edit_time = edit_time - thread.save() + thread.save(update_fields=['last_edit_time']) def get_url(self, thread=None): """ @@ -341,7 +338,7 @@ class Post(models.Model, Viewable): def delete(self, using=None): """ - Delete all post images and the post itself. + Deletes all post images and the post itself. """ self.images.all().delete() diff --git a/boards/models/tag.py b/boards/models/tag.py --- a/boards/models/tag.py +++ b/boards/models/tag.py @@ -38,7 +38,6 @@ class Tag(models.Model, Viewable): name = models.CharField(max_length=100, db_index=True) threads = models.ManyToManyField(Thread, null=True, blank=True, related_name='tag+') - linked = models.ForeignKey('Tag', null=True, blank=True) def __unicode__(self): return self.name @@ -53,31 +52,6 @@ class Tag(models.Model, Viewable): def get_thread_count(self): return self.threads.count() - def get_linked_tags(self): - """ - Gets tags linked to the current one. - """ - - tag_list = [] - self.get_linked_tags_list(tag_list) - - return tag_list - - def get_linked_tags_list(self, tag_list=None): - """ - Returns the list of tags linked to current. The list can be got - through returned value or tag_list parameter - """ - if not tag_list: - tag_list = [] - - linked_tag = self.linked - - if linked_tag and not (linked_tag in tag_list): - tag_list.append(linked_tag) - - linked_tag.get_linked_tags_list(tag_list) - def get_post_count(self, archived=False): """ Gets posts count for the tag's threads. diff --git a/boards/static/css/md/base_page.css b/boards/static/css/md/base_page.css --- a/boards/static/css/md/base_page.css +++ b/boards/static/css/md/base_page.css @@ -226,11 +226,13 @@ blockquote { } .multiquote { - color: #92cf38; - font-style: italic; - border-left: solid 3px #00aa00; - padding-left: 3px; + border-left: solid 4px #ccc; + padding: 3px; display: inline-block; + background: #222; + border-right: solid 1px #ccc; + border-top: solid 1px #ccc; + border-bottom: solid 1px #ccc; } .spoiler { diff --git a/boards/tests.py b/boards/tests.py --- a/boards/tests.py +++ b/boards/tests.py @@ -13,6 +13,8 @@ from boards import urls from boards import settings import neboard +TEST_TAG = 'test_tag' + PAGE_404 = 'boards/404.html' TEST_TEXT = 'test text' @@ -31,14 +33,18 @@ logger = logging.getLogger(__name__) class PostTests(TestCase): def _create_post(self): - return Post.objects.create_post(title='title', text='text') + tag = Tag.objects.create(name=TEST_TAG) + return Post.objects.create_post(title='title', text='text', + tags=[tag]) def test_post_add(self): """Test adding post""" post = self._create_post() - self.assertIsNotNone(post, 'No post was created') + self.assertIsNotNone(post, 'No post was created.') + self.assertEqual(TEST_TAG, post.get_thread().tags.all()[0].name, + 'No tags were added to the post.') def test_delete_post(self): """Test post deletion""" @@ -131,17 +137,6 @@ class PostTests(TestCase): self.assertEqual(all_threads[settings.THREADS_PER_PAGE].id, first_post.id) - def test_linked_tag(self): - """Test adding a linked tag""" - - linked_tag = Tag.objects.create(name=u'tag1') - tag = Tag.objects.create(name=u'tag2', linked=linked_tag) - - post = Post.objects.create_post("", "", tags=[tag]) - - self.assertTrue(linked_tag in post.get_thread().tags.all(), - 'Linked tag was not added') - class PagesTest(TestCase): @@ -272,4 +267,4 @@ class AbstractTest(TestCase): class MockRequest: def __init__(self): - self.session = dict() \ No newline at end of file + self.session = dict() diff --git a/changelog.markdown b/changelog.markdown --- a/changelog.markdown +++ b/changelog.markdown @@ -35,3 +35,8 @@ elements instead of swapping them images to a post * Added search over posts and tags * [ADMIN] Command to remove empty users + +# 2.0 D'Anna +* Removed users. Now settings are stored in sessions +* Changed markdown to bbcode +* Removed linked tags