diff options
38 files changed, 1694 insertions, 2 deletions
@@ -0,0 +1,11 @@ +Copyright 2018 Yaroslav de la Peña Smirnov + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..5621115 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,5 @@ +include LICENSE +include README.rst +recursive-include weblog/static * +recursive-include weblog/templates * +recursive-include weblog/locale *
\ No newline at end of file @@ -1,2 +1,32 @@ -# django-weblog -A simple blog engine for Django with multilingual capabilities + +# Weblog version 0.2 # + +Weblog is a simple blog engine for Django, with some focus on multilingual capabilities. It includes all of the basic features expected of a traditional Web log (also known as blog), as well as multilingual features, i.e. translations of blog posts which are delivered automatically in the user's preferred language using the internationalization capabilities of Django, enabling the possibility of targeting people from different countries in a single blog/site. + +This django app is still a work in progress. More features will be added/completed in the near future. Currently the app's strings are translated only to English (en), Russian (ru), and Spanish (es), + +### Quick Start ### + +1. Add "weblog" to your INSTALLED_APPS setting in your settings.py + +2. Include the app in your project's urls.py; for example: + + url(r'^blog/', include('weblog.urls')), + +3. Migrate the models to the database by running "python manage.py migrate" + +4. You can configure and customize the blog by adding and modifying to your liking/needs the following settings to your settings.py: + + WEBLOG_ENABLE_COMMENTS = True #Should comments be allowed on your blog + WEBLOG_ALLOW_ANON_COMMENTS = False #Are visitors allowed to leave comments without signing in (note that you should provide a way for them to register and login if you wish to allow only registered user's comments) + WEBLOG_MULTILINGUAL = True #Enable multilingual features of the weblog app (i.e.: BlogPost and Category translations) + WEBLOG_TITLE = 'Weblog Test' #The name/title of your blog (e.g.: Example Site Newsletter) + WEBLOG_BASE_TEMPLATE = 'site_base.html' #Which base template to use (if not indicated, it will use its own base template) + WEBLOG_SHOW_AUTHOR = True #Should the author of the post be shown (it uses the Django User model) + WEBLOG_USE_AUTHORS_USERNAME = True #Show the username of the author instead of the fullname + WEBLOG_SHOW_SIDEBAR = True #Enable the sidebar + WEBLOG_SHOW_CATEGORIES = True #Show links to categories in the sidebar + WEBLOG_SHOW_ARCHIVE = True #Show the archive treeview (Years>Months) in the sidebar + WEBLOG_POSTS_PER_PAGE = 10 #Number of posts that should be shown per page + +5. Note that if you use your own base template, you will either need to link bootstrap in your base template's head, or write your own styles for the site based on the bootstrap classes. You will as well need to link files "weblog/css/weblog.css" and "weblog/js/weblog.js" in your html head.
\ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..88265df --- /dev/null +++ b/setup.py @@ -0,0 +1,36 @@ +import os +from setuptools import find_packages, setup + +with open(os.path.join(os.path.dirname(__file__), 'README.md')) as readme: + README = readme.read() + +# allow setup.py to be run from any path +os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir))) + +setup( + name='django-weblog', + version='0.2.1', + packages=find_packages(), + include_package_data=True, + license='BSD License', + description='A simple blog engine for Django with multilingual capabilities.', + long_description=README, + url='https://www.yaroslavps.com/', + author='Yaroslav de la Peña Smirnov', + author_email='contact@yaroslavps.com', + classifiers=[ + 'Environment :: Web Environment', + 'Framework :: Django', + 'Framework :: Django :: 1.11', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: BSD License', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Topic :: Internet :: WWW/HTTP', + 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', + ], +)
\ No newline at end of file diff --git a/weblog/__init__.py b/weblog/__init__.py new file mode 100644 index 0000000..a97f18a --- /dev/null +++ b/weblog/__init__.py @@ -0,0 +1,79 @@ +from . import apps +from django.conf import settings + +try: + apps.SETTINGS['enable_comments'] = settings.WEBLOG_ENABLE_COMMENTS +except AttributeError: + pass +except NameError: + pass + +try: + apps.SETTINGS['allow_anon_comments'] = settings.WEBLOG_ALLOW_ANON_COMMENTS +except AttributeError: + pass +except NameError: + pass + +try: + apps.SETTINGS['multilingual'] = settings.WEBLOG_MULTILINGUAL +except AttributeError: + pass +except NameError: + pass + +try: + apps.SETTINGS['blog_title'] = settings.WEBLOG_TITLE +except AttributeError: + pass +except NameError: + pass + +try: + apps.SETTINGS['base_template'] = settings.WEBLOG_BASE_TEMPLATE +except AttributeError: + pass +except NameError: + pass + +try: + apps.SETTINGS['show_author'] = settings.WEBLOG_SHOW_AUTHOR +except AttributeError: + pass +except NameError: + pass + +try: + apps.SETTINGS['use_authors_username'] = settings.WEBLOG_USE_AUTHORS_USERNAME +except AttributeError: + pass +except NameError: + pass + +try: + apps.SETTINGS['show_sidebar'] = settings.WEBLOG_SHOW_SIDEBAR +except AttributeError: + pass +except NameError: + pass + +try: + apps.SETTINGS['show_categories'] = settings.WEBLOG_SHOW_CATEGORIES +except AttributeError: + pass +except NameError: + pass + +try: + apps.SETTINGS['show_archive'] = settings.WEBLOG_SHOW_ARCHIVE +except AttributeError: + pass +except NameError: + pass + +try: + apps.SETTINGS['posts_per_page'] = settings.WEBLOG_POSTS_PER_PAGE +except AttributeError: + pass +except NameError: + pass
\ No newline at end of file diff --git a/weblog/admin.py b/weblog/admin.py new file mode 100644 index 0000000..1b4e128 --- /dev/null +++ b/weblog/admin.py @@ -0,0 +1,46 @@ +from django.contrib import admin +from django_summernote.admin import SummernoteModelAdmin, SummernoteInlineModelAdmin +from .apps import SETTINGS as blog_settings +from .models import BlogPost, Translation, PostComment, Category, CategoryTranslation + + +blogPostInlines = [] +categoryInlines = [] + +class TranslationInline(admin.StackedInline, SummernoteInlineModelAdmin): + model = Translation + extra = 1 + +class CategoryTranslationInline(admin.StackedInline): + model = CategoryTranslation + extra = 1 + +class PostCommentInline(admin.StackedInline): + model = PostComment + extra = 0 + +if blog_settings['multilingual']: + blogPostInlines.append(TranslationInline) + categoryInlines.append(CategoryTranslationInline) + +if blog_settings['enable_comments']: + blogPostInlines.append(PostCommentInline) + +class BlogPostAdmin(SummernoteModelAdmin): + list_display = ['title', 'author', 'publish_date'] + list_filter = ['publish_date', 'categories'] + inlines = blogPostInlines + summer_note_fields = '__all__' + + def get_form(self, request, obj=None, **kwargs): + if not blog_settings['multilingual']: + self.exclude = ('original_language', ) + form = super(BlogPostAdmin, self).get_form(request, obj, **kwargs) + return form + +class CategoryAdmin(admin.ModelAdmin): + list_display = ['name'] + inlines = categoryInlines + +admin.site.register(BlogPost, BlogPostAdmin) +admin.site.register(Category, CategoryAdmin) diff --git a/weblog/apps.py b/weblog/apps.py new file mode 100644 index 0000000..3389f92 --- /dev/null +++ b/weblog/apps.py @@ -0,0 +1,18 @@ +from django.apps import AppConfig + +SETTINGS = { + 'enable_comments': False, + 'allow_anon_comments': True, + 'multilingual': True, + 'blog_title': 'Django-Weblog', + 'base_template': 'base.html', + 'show_author': True, + 'use_authors_username': True, + 'show_sidebar': True, + 'show_categories': False, + 'show_archive': True, + 'posts_per_page': 10, +} + +class WeblogConfig(AppConfig): + name = 'weblog' diff --git a/weblog/locale/es/LC_MESSAGES/django.mo b/weblog/locale/es/LC_MESSAGES/django.mo Binary files differnew file mode 100644 index 0000000..9558ef1 --- /dev/null +++ b/weblog/locale/es/LC_MESSAGES/django.mo diff --git a/weblog/locale/es/LC_MESSAGES/django.po b/weblog/locale/es/LC_MESSAGES/django.po new file mode 100644 index 0000000..5afb637 --- /dev/null +++ b/weblog/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,274 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-31 08:00+0300\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: weblog/models.py:8 weblog/models.py:23 +msgctxt "Noun, not personal name" +msgid "Name" +msgstr "Nombre" + +#: weblog/models.py:9 weblog/models.py:45 +msgid "Slug (URL)" +msgstr "" + +#: weblog/models.py:10 +msgid "Parent category" +msgstr "Categoría raíz" + +#: weblog/models.py:19 weblog/models.py:25 +msgctxt "Post category" +msgid "Category" +msgstr "Categoría" + +#: weblog/models.py:20 weblog/models.py:46 weblog/templates/weblog/post.html:16 +#: weblog/templates/weblog/sidebar_categories.html:3 +msgctxt "Post categories" +msgid "Categories" +msgstr "Categorías" + +#: weblog/models.py:24 weblog/models.py:67 +msgid "Language (ISO)" +msgstr "Idioma (ISO)" + +#: weblog/models.py:34 +msgid "Category name translation" +msgstr "Traducción de la categoría" + +#: weblog/models.py:35 +msgid "Category name translations" +msgstr "Traducciones de categorías" + +#: weblog/models.py:39 weblog/models.py:78 +msgid "Author" +msgstr "Autor" + +#: weblog/models.py:40 weblog/models.py:68 +msgctxt "As in name" +msgid "Title" +msgstr "Título" + +#: weblog/models.py:41 weblog/models.py:69 weblog/models.py:80 +msgctxt "Of post, comment, article, etc." +msgid "Content" +msgstr "Contenido" + +#: weblog/models.py:42 weblog/models.py:70 +msgid "Preview image" +msgstr "Imágen de vista previa" + +#: weblog/models.py:43 weblog/models.py:71 +msgid "Preview Text" +msgstr "Texto de vista previa" + +#: weblog/models.py:44 +msgid "Original language (ISO)" +msgstr "Idioma original" + +#: weblog/models.py:47 +msgctxt "Make post viewable" +msgid "Published" +msgstr "Publicado" + +#: weblog/models.py:48 +msgid "Publish date" +msgstr "Fecha de publicación" + +#: weblog/models.py:62 +msgid "Blog Post" +msgstr "Entrada de blog" + +#: weblog/models.py:63 +msgid "Blog Posts" +msgstr "Entradas de blog" + +#: weblog/models.py:66 weblog/models.py:79 +#, fuzzy +#| msgid "Blog Post" +msgctxt "Noun, as in blog post" +msgid "Post" +msgstr "Entrada" + +#: weblog/models.py:74 +msgid "Translation" +msgstr "Traducción" + +#: weblog/models.py:75 +msgid "Translations" +msgstr "Traducciones" + +#: weblog/models.py:83 +msgctxt "Noun" +msgid "Comment" +msgstr "Comentario" + +#: weblog/models.py:84 +msgctxt "Noun" +msgid "Comments" +msgstr "Comentarios" + +#: weblog/templates/weblog/index.html:6 weblog/templatetags/weblog_extras.py:43 +#: weblog/views.py:75 weblog/views.py:150 +msgctxt "Posts without category" +msgid "Uncategorized" +msgstr "Sin categoría" + +#: weblog/templates/weblog/index.html:17 +msgctxt "Uncategorized page title" +msgid "Uncategorized posts" +msgstr "Entradas sin categoría" + +#: weblog/templates/weblog/index.html:19 +#, python-format +msgctxt "Posts in category" +msgid "Posts in %(category_name)s" +msgstr "Entradas en %(category_name)s" + +#: weblog/templates/weblog/index.html:28 weblog/templates/weblog/post.html:7 +#, python-format +msgid "Published on %(publish_date)s" +msgstr "Publicado el %(publish_date)s" + +#: weblog/templates/weblog/index.html:28 weblog/templates/weblog/post.html:7 +#, python-format +msgctxt "Written by (Author)" +msgid ", by %(author)s" +msgstr ", por %(author)s" + +#: weblog/templates/weblog/index.html:34 +msgid "Read more..." +msgstr "Leer más..." + +#: weblog/templates/weblog/index.html:41 +msgctxt "Page" +msgid "First" +msgstr "Primera" + +#: weblog/templates/weblog/index.html:42 +msgctxt "Page" +msgid "Previous" +msgstr "Anterior" + +#: weblog/templates/weblog/index.html:70 +msgctxt "Page" +msgid "Next" +msgstr "Siguiente" + +#: weblog/templates/weblog/index.html:71 +msgctxt "Page" +msgid "Last" +msgstr "Última" + +#: weblog/templates/weblog/index.html:76 +msgid "Nothing has been posted yet." +msgstr "No hay ninguna publicación." + +#: weblog/templates/weblog/post.html:24 +msgid "Leave a comment" +msgstr "Dejar un comentario" + +#: weblog/templates/weblog/post.html:31 +msgid "Submit comment" +msgstr "Enviar comentario" + +#: weblog/templates/weblog/post.html:35 +msgid "To leave a comment you need to sign in" +msgstr "Para poder comentar, necesitar iniciar sesión." + +#: weblog/templates/weblog/post.html:47 +msgid "Comment submited successfully" +msgstr "Comentario enviado exitosamente" + +#: weblog/templates/weblog/post.html:54 +msgctxt "Unauthenticated comment poster" +msgid "Anonymous" +msgstr "Anónimo" + +#: weblog/templates/weblog/post.html:62 +msgid "Nobody has left a comment on this post yet" +msgstr "No hay ningún comentario relacionado a esta entrada" + +#: weblog/templates/weblog/sidebar_archive.html:2 +msgctxt "Blog archive" +msgid "Archive" +msgstr "Archivo" + +#: weblog/templatetags/weblog_extras.py:12 +msgid "January" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:13 +msgid "February" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:14 +msgid "March" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:15 +msgid "April" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:16 +msgid "May" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:17 +msgid "June" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:18 +msgid "July" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:19 +msgid "August" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:20 +msgid "September" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:21 +msgid "October" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:22 +msgid "November" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:23 +msgid "December" +msgstr "" + +#: weblog/views.py:171 +msgid "You need to sign in to submit a comment" +msgstr "Para poder comentar necesita iniciar sesión" + +#: weblog/views.py:173 +msgid "Error submitting comment: Invalid data" +msgstr "Error al intentar enviar el comentario: Información invalida" + +#~ msgid "English" +#~ msgstr "Inglés" + +#~ msgid "Spanish" +#~ msgstr "Español" + +#~ msgid "Russian" +#~ msgstr "Ruso" diff --git a/weblog/locale/ru/LC_MESSAGES/django.mo b/weblog/locale/ru/LC_MESSAGES/django.mo Binary files differnew file mode 100644 index 0000000..a419335 --- /dev/null +++ b/weblog/locale/ru/LC_MESSAGES/django.mo diff --git a/weblog/locale/ru/LC_MESSAGES/django.po b/weblog/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000..e586fbd --- /dev/null +++ b/weblog/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,274 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-31 08:00+0300\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" +"%100>=11 && n%100<=14)? 2 : 3);\n" + +#: weblog/models.py:8 weblog/models.py:23 +msgctxt "Noun, not personal name" +msgid "Name" +msgstr "Название" + +#: weblog/models.py:9 weblog/models.py:45 +msgid "Slug (URL)" +msgstr "" + +#: weblog/models.py:10 +msgid "Parent category" +msgstr "Корневая категория" + +#: weblog/models.py:19 weblog/models.py:25 +msgctxt "Post category" +msgid "Category" +msgstr "Категория" + +#: weblog/models.py:20 weblog/models.py:46 weblog/templates/weblog/post.html:16 +#: weblog/templates/weblog/sidebar_categories.html:3 +msgctxt "Post categories" +msgid "Categories" +msgstr "Категории" + +#: weblog/models.py:24 weblog/models.py:67 +msgid "Language (ISO)" +msgstr "Язык (В стандарте ISO)" + +#: weblog/models.py:34 +msgid "Category name translation" +msgstr "Перевод названия категории" + +#: weblog/models.py:35 +msgid "Category name translations" +msgstr "Переводы названия категории" + +#: weblog/models.py:39 weblog/models.py:78 +msgid "Author" +msgstr "Автор" + +#: weblog/models.py:40 weblog/models.py:68 +msgctxt "As in name" +msgid "Title" +msgstr "Название" + +#: weblog/models.py:41 weblog/models.py:69 weblog/models.py:80 +msgctxt "Of post, comment, article, etc." +msgid "Content" +msgstr "Содержание" + +#: weblog/models.py:42 weblog/models.py:70 +msgid "Preview image" +msgstr "Картинка предпросмотра" + +#: weblog/models.py:43 weblog/models.py:71 +msgid "Preview Text" +msgstr "Текст предпросмотра" + +#: weblog/models.py:44 +msgid "Original language (ISO)" +msgstr "Язык оригинала (в стандарте ISO)" + +#: weblog/models.py:47 +msgctxt "Make post viewable" +msgid "Published" +msgstr "Опубликовать" + +#: weblog/models.py:48 +msgid "Publish date" +msgstr "Дата публикации" + +#: weblog/models.py:62 +msgid "Blog Post" +msgstr "Запись блога" + +#: weblog/models.py:63 +msgid "Blog Posts" +msgstr "Записи блога" + +#: weblog/models.py:66 weblog/models.py:79 +msgctxt "Noun, as in blog post" +msgid "Post" +msgstr "Запись" + +#: weblog/models.py:74 +msgid "Translation" +msgstr "Перевод" + +#: weblog/models.py:75 +msgid "Translations" +msgstr "Переводы" + +#: weblog/models.py:83 +msgctxt "Noun" +msgid "Comment" +msgstr "Комментарий" + +#: weblog/models.py:84 +msgctxt "Noun" +msgid "Comments" +msgstr "Комментарии" + +#: weblog/templates/weblog/index.html:6 weblog/templatetags/weblog_extras.py:43 +#: weblog/views.py:75 weblog/views.py:150 +msgctxt "Posts without category" +msgid "Uncategorized" +msgstr "Без категории" + +#: weblog/templates/weblog/index.html:17 +msgctxt "Uncategorized page title" +msgid "Uncategorized posts" +msgstr "Записи без категории" + +#: weblog/templates/weblog/index.html:19 +#, python-format +msgctxt "Posts in category" +msgid "Posts in %(category_name)s" +msgstr "Записи в %(category_name)s" + +#: weblog/templates/weblog/index.html:28 weblog/templates/weblog/post.html:7 +#, python-format +msgid "Published on %(publish_date)s" +msgstr "Опубликовано %(publish_date)s" + +#: weblog/templates/weblog/index.html:28 weblog/templates/weblog/post.html:7 +#, python-format +msgctxt "Written by (Author)" +msgid ", by %(author)s" +msgstr ". %(author)s" + +#: weblog/templates/weblog/index.html:34 +msgid "Read more..." +msgstr "Читать далее..." + +#: weblog/templates/weblog/index.html:41 +msgctxt "Page" +msgid "First" +msgstr "Первая" + +#: weblog/templates/weblog/index.html:42 +msgctxt "Page" +msgid "Previous" +msgstr "Предыдущая" + +#: weblog/templates/weblog/index.html:70 +msgctxt "Page" +msgid "Next" +msgstr "Следующая" + +#: weblog/templates/weblog/index.html:71 +msgctxt "Page" +msgid "Last" +msgstr "Последняя" + +#: weblog/templates/weblog/index.html:76 +msgid "Nothing has been posted yet." +msgstr "Нет записи на данный момент." + +#: weblog/templates/weblog/post.html:24 +msgid "Leave a comment" +msgstr "Оставьте комментарий" + +#: weblog/templates/weblog/post.html:31 +msgid "Submit comment" +msgstr "Отправить комметарий" + +#: weblog/templates/weblog/post.html:35 +msgid "To leave a comment you need to sign in" +msgstr "Для того чтобы оставить комментарий, зайдите в свою учетную запись" + +#: weblog/templates/weblog/post.html:47 +msgid "Comment submited successfully" +msgstr "Ваш комментарий был успешно отправлен" + +#: weblog/templates/weblog/post.html:54 +msgctxt "Unauthenticated comment poster" +msgid "Anonymous" +msgstr "Анонимный" + +#: weblog/templates/weblog/post.html:62 +msgid "Nobody has left a comment on this post yet" +msgstr "У этой записи нет комментарии." + +#: weblog/templates/weblog/sidebar_archive.html:2 +msgctxt "Blog archive" +msgid "Archive" +msgstr "Архив" + +#: weblog/templatetags/weblog_extras.py:12 +msgid "January" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:13 +msgid "February" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:14 +msgid "March" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:15 +msgid "April" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:16 +msgid "May" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:17 +msgid "June" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:18 +msgid "July" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:19 +msgid "August" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:20 +msgid "September" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:21 +msgid "October" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:22 +msgid "November" +msgstr "" + +#: weblog/templatetags/weblog_extras.py:23 +msgid "December" +msgstr "" + +#: weblog/views.py:171 +msgid "You need to sign in to submit a comment" +msgstr "Для того чтобы оставить комментарий, зайдите в свою учетную запись" + +#: weblog/views.py:173 +msgid "Error submitting comment: Invalid data" +msgstr "Ошибка: неправильный формат данных" + +#~ msgid "English" +#~ msgstr "Английский" + +#~ msgid "Spanish" +#~ msgstr "Испанский" + +#~ msgid "Russian" +#~ msgstr "Русский" diff --git a/weblog/migrations/0001_initial.py b/weblog/migrations/0001_initial.py new file mode 100644 index 0000000..2ab0238 --- /dev/null +++ b/weblog/migrations/0001_initial.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.8 on 2018-01-09 08:02 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='BlogPost', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=100, verbose_name='Title')), + ('content', models.TextField(verbose_name='Content')), + ('preview_image', models.ImageField(blank=True, upload_to='weblog/preview_images/%Y/%m/%d/', verbose_name='Preview image')), + ('preview_text', models.CharField(blank=True, max_length=250, verbose_name='Preview Text')), + ('original_language', models.CharField(max_length=5, verbose_name='Original language (ISO)')), + ('publish_date', models.DateTimeField(verbose_name='Publish date')), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Author')), + ], + options={ + 'verbose_name': 'Blog Post', + 'verbose_name_plural': 'Blog Posts', + }, + ), + migrations.CreateModel( + name='PostComment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('content', models.TextField(verbose_name='Content')), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Author')), + ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='weblog.BlogPost', verbose_name='Post')), + ], + options={ + 'verbose_name': 'Comment', + 'verbose_name_plural': 'Comments', + }, + ), + migrations.CreateModel( + name='Translation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('language', models.CharField(max_length=5, verbose_name='Language (ISO)')), + ('title', models.CharField(max_length=100, verbose_name='Title')), + ('content', models.TextField(verbose_name='Content')), + ('preview_image', models.ImageField(blank=True, upload_to='weblog/preview_images/%Y/%m/%d/', verbose_name='Preview image')), + ('preview_text', models.CharField(blank=True, max_length=250, verbose_name='Preview Text')), + ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='weblog.BlogPost', verbose_name='Post')), + ], + options={ + 'verbose_name': 'Translation', + 'verbose_name_plural': 'Translations', + }, + ), + ] diff --git a/weblog/migrations/0002_auto_20180113_1606.py b/weblog/migrations/0002_auto_20180113_1606.py new file mode 100644 index 0000000..8eb3789 --- /dev/null +++ b/weblog/migrations/0002_auto_20180113_1606.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.8 on 2018-01-13 13:06 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('weblog', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Category', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=250, verbose_name='Name')), + ('parent_category', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, to='weblog.Category', verbose_name='Parent category')), + ], + options={ + 'verbose_name': 'Category', + 'verbose_name_plural': 'Categories', + }, + ), + migrations.CreateModel( + name='CategoryTranslation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=250, verbose_name='Name')), + ('language', models.CharField(max_length=5, verbose_name='Language (ISO)')), + ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='weblog.Category', verbose_name='Category')), + ], + options={ + 'verbose_name': 'Category name translation', + 'verbose_name_plural': 'Category name translations', + }, + ), + migrations.AddField( + model_name='blogpost', + name='published', + field=models.BooleanField(default=False, verbose_name='Published'), + preserve_default=False, + ), + migrations.AlterField( + model_name='blogpost', + name='original_language', + field=models.CharField(blank=True, max_length=5, verbose_name='Original language (ISO)'), + ), + migrations.AddField( + model_name='blogpost', + name='category', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='weblog.Category', verbose_name='Category'), + ), + ] diff --git a/weblog/migrations/0003_auto_20180119_0156.py b/weblog/migrations/0003_auto_20180119_0156.py new file mode 100644 index 0000000..73ca4e1 --- /dev/null +++ b/weblog/migrations/0003_auto_20180119_0156.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.8 on 2018-01-18 22:56 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('weblog', '0002_auto_20180113_1606'), + ] + + operations = [ + migrations.AlterModelOptions( + name='blogpost', + options={'ordering': ['-publish_date', 'title'], 'verbose_name': 'Blog Post', 'verbose_name_plural': 'Blog Posts'}, + ), + migrations.RemoveField( + model_name='blogpost', + name='category', + ), + migrations.AddField( + model_name='blogpost', + name='categories', + field=models.ManyToManyField(blank=True, to='weblog.Category', verbose_name='Categories'), + ), + ] diff --git a/weblog/migrations/0004_auto_20180119_0156.py b/weblog/migrations/0004_auto_20180119_0156.py new file mode 100644 index 0000000..937b7a0 --- /dev/null +++ b/weblog/migrations/0004_auto_20180119_0156.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.8 on 2018-01-18 22:56 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('weblog', '0003_auto_20180119_0156'), + ] + + operations = [ + migrations.AlterField( + model_name='category', + name='parent_category', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='weblog.Category', verbose_name='Parent category'), + ), + ] diff --git a/weblog/migrations/0005_auto_20180119_0231.py b/weblog/migrations/0005_auto_20180119_0231.py new file mode 100644 index 0000000..42b1bd0 --- /dev/null +++ b/weblog/migrations/0005_auto_20180119_0231.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.8 on 2018-01-18 23:31 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('weblog', '0004_auto_20180119_0156'), + ] + + operations = [ + migrations.AlterField( + model_name='category', + name='name', + field=models.CharField(max_length=250, unique=True, verbose_name='Name'), + ), + ] diff --git a/weblog/migrations/0006_auto_20180121_1002.py b/weblog/migrations/0006_auto_20180121_1002.py new file mode 100644 index 0000000..db56a3f --- /dev/null +++ b/weblog/migrations/0006_auto_20180121_1002.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.8 on 2018-01-21 07:02 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('weblog', '0005_auto_20180119_0231'), + ] + + operations = [ + migrations.AddField( + model_name='blogpost', + name='slug', + field=models.SlugField(default='Test', max_length=100, unique=True, verbose_name='Slug (URL)'), + preserve_default=False, + ), + migrations.AddField( + model_name='category', + name='slug', + field=models.SlugField(default='Test', max_length=60, unique=True, verbose_name='Slug (URL)'), + preserve_default=False, + ), + ] diff --git a/weblog/migrations/0007_auto_20180122_1943.py b/weblog/migrations/0007_auto_20180122_1943.py new file mode 100644 index 0000000..cae0a4f --- /dev/null +++ b/weblog/migrations/0007_auto_20180122_1943.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.8 on 2018-01-22 16:43 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('weblog', '0006_auto_20180121_1002'), + ] + + operations = [ + migrations.AlterField( + model_name='postcomment', + name='author', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Author'), + ), + ] diff --git a/weblog/migrations/__init__.py b/weblog/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/weblog/migrations/__init__.py diff --git a/weblog/models.py b/weblog/models.py new file mode 100644 index 0000000..80e917e --- /dev/null +++ b/weblog/models.py @@ -0,0 +1,93 @@ +from django.db import models +from django.shortcuts import reverse +from django.contrib.auth.models import User +from django.forms import ModelForm, Textarea +from django.utils.translation import ugettext_lazy as _, pgettext_lazy + +class Category(models.Model): + name = models.CharField(max_length=250, verbose_name=pgettext_lazy('Noun, not personal name', 'Name'), blank=False, unique=True) + slug = models.SlugField(max_length=60, verbose_name=_('Slug (URL)'), db_index=True, unique=True) + parent_category = models.ForeignKey('self', verbose_name=_('Parent category'), null=True, blank=True) + + def get_absolute_url(self): + return reverse('weblog:CategoryIndex', kwargs={'category_slug': self.slug}) + + def __str__(self): + return self.name + + class Meta: + verbose_name = pgettext_lazy('Post category', 'Category') + verbose_name_plural = pgettext_lazy('Post categories', 'Categories') + +class CategoryTranslation(models.Model): + name = models.CharField(max_length=250, verbose_name=pgettext_lazy('Noun, not personal name', 'Name'), blank=False) + language = models.CharField(max_length=5, verbose_name=_('Language (ISO)'), blank=False) + category = models.ForeignKey(Category, verbose_name = pgettext_lazy('Post category', 'Category'), blank=False) + + def __str__(self): + return self.name + + def slug(self): + return self.category.slug + + class Meta: + verbose_name = _('Category name translation') + verbose_name_plural = _('Category name translations') + + +class BlogPost(models.Model): + author = models.ForeignKey(User, verbose_name=_('Author')) + title = models.CharField(max_length=100, verbose_name=pgettext_lazy('As in name', 'Title'), blank=False) + content = models.TextField(verbose_name=pgettext_lazy('Of post, comment, article, etc.', 'Content'), blank=False) + preview_image = models.ImageField(upload_to='weblog/preview_images/%Y/%m/%d/', blank=True, verbose_name=_('Preview image')) + preview_text = models.CharField(max_length=250, blank=True, verbose_name=_('Preview Text')) + original_language = models.CharField(max_length=5, verbose_name=_('Original language (ISO)'), blank=True) + slug = models.SlugField(max_length=100, verbose_name=_('Slug (URL)'), db_index=True, unique=True) + categories = models.ManyToManyField(Category, verbose_name=pgettext_lazy('Post categories', 'Categories'), blank=True) + published = models.BooleanField(verbose_name=pgettext_lazy('Make post viewable', 'Published')) + publish_date = models.DateTimeField(verbose_name=_('Publish date')) + + def get_absolute_url(self): + if self.categories.all().count() > 0: + category = self.categories.all()[0].slug + return reverse('weblog:PostView', kwargs={'category_slug': category, 'post_slug': self.slug}) + else: + return reverse('weblog:PostView', kwargs={'category_slug': 'misc', 'post_slug': self.slug}) + + def __str__(self): + return self.title + + class Meta: + ordering = ['-publish_date', 'title'] + verbose_name = _('Blog Post') + verbose_name_plural = _('Blog Posts') + +class Translation(models.Model): + post = models.ForeignKey(BlogPost, verbose_name=pgettext_lazy('Noun, as in blog post', 'Post')) + language = models.CharField(max_length=5, verbose_name=_('Language (ISO)'), blank=False) + title = models.CharField(max_length=100, verbose_name=pgettext_lazy('As in name', 'Title'), blank=False) + content = models.TextField(verbose_name=pgettext_lazy('Of post, comment, article, etc.', 'Content'), blank=False) + preview_image = models.ImageField(upload_to='weblog/preview_images/%Y/%m/%d/', blank=True, verbose_name=_('Preview image')) + preview_text = models.CharField(max_length=250, blank=True, verbose_name=_('Preview Text')) + + class Meta: + verbose_name = _('Translation') + verbose_name_plural = _('Translations') + +class PostComment(models.Model): + author = models.ForeignKey(User, verbose_name=_('Author'), null=True, blank=True) + post = models.ForeignKey(BlogPost, verbose_name=pgettext_lazy('Noun, as in blog post', 'Post')) + content = models.TextField(verbose_name=pgettext_lazy('Of post, comment, article, etc.', 'Content'), blank=False) + + class Meta: + verbose_name = pgettext_lazy('Noun', 'Comment') + verbose_name_plural = pgettext_lazy('Noun', 'Comments') + +class PostCommentForm(ModelForm): + class Meta: + model = PostComment + fields = ('content',) + labels = {'content': ''} + widgets = { + 'content': Textarea(attrs={'class': 'form-control', 'rows': '5'}), + }
\ No newline at end of file diff --git a/weblog/static/weblog/css/weblog.css b/weblog/static/weblog/css/weblog.css new file mode 100644 index 0000000..cb1facc --- /dev/null +++ b/weblog/static/weblog/css/weblog.css @@ -0,0 +1,7 @@ +.archive-list{ + list-style-type: none; +} + +.archive-child-list{ + display: none; +}
\ No newline at end of file diff --git a/weblog/static/weblog/js/weblog.js b/weblog/static/weblog/js/weblog.js new file mode 100644 index 0000000..b802841 --- /dev/null +++ b/weblog/static/weblog/js/weblog.js @@ -0,0 +1,13 @@ +function toggleNode(caller){ + state = $(caller).attr('node-state'); + target = $(caller).attr('node-target'); + if(state=='closed'){ + $(caller).html('—'); + $(caller).attr('node-state', 'open'); + } + else{ + $(caller).html('+'); + $(caller).attr('node-state', 'closed'); + } + $('#'+target).toggle(); +}
\ No newline at end of file diff --git a/weblog/templates/weblog/index.html b/weblog/templates/weblog/index.html new file mode 100644 index 0000000..c46da38 --- /dev/null +++ b/weblog/templates/weblog/index.html @@ -0,0 +1,78 @@ +{% extends 'weblog/weblog.html' %}
+{% load i18n %}
+{% block title_block %}
+{% if category %}
+{% if category == 'misc' %}
+{% trans 'Uncategorized' context 'Posts without category' %}
+{% else %}
+{{ category.name }}
+{% endif %}
+{% else %}
+{{ blog_title }}
+{% endif %}
+{% endblock %}
+{% block blog_content_block %}
+{% if category %}
+{% if category == 'misc' %}
+<h1>{% trans 'Uncategorized posts' context 'Uncategorized page title' %}</h1>
+{% else %}
+<h1>{% blocktrans with category_name=category.name context 'Posts in category' %}Posts in {{ category_name }}{% endblocktrans %}</h1>
+{% endif %}
+{% else %}
+<h1>{{ blog_title }}</h1>
+{% endif %}
+ {% if posts %}
+ {% for post in posts %}
+ <div class="container-fluid blogpost">
+ <h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
+ <p class="publish-info">{% blocktrans with publish_date=post.publish_date %}Published on {{ publish_date }}{% endblocktrans %}{% if post.author %}{% blocktrans with author=post.author context 'Written by (Author)' %}, by {{ author }}{% endblocktrans %}{% endif %}</p>
+ <hr>
+ {% if post.preview_image %}<img class="img-responsive preview-img" src="{{ post.preview_image.url }}">{% endif %}
+ {{ post.preview_text|safe }}
+ <hr>
+ <div class="text-right">
+ <a href="{{ post.url }}">{% trans 'Read more...' %}</a>
+ </div>
+ </div>
+ {% endfor %}
+ {% if last_page > 1 %}
+ <ul class="pagination">
+ {% if current_page != 1 %}
+ <li title="{% trans 'First' context 'Page' %}"><a href="{% if category %}{% if category == 'misc' %}{% url 'weblog:CategoryIndex' category_slug='misc' %}{% else %}{% url 'weblog:CategoryIndex' category_slug=category.slug %}{% endif %}{% else %}{% url 'weblog:Index' %}{% endif %}">«</a></li>
+ <li title="{% trans 'Previous' context 'Page' %}"><a href="{% if category %}{% if category == 'misc' %}{% url 'weblog:CategoryIndex' category_slug='misc' %}?page={{ current_page|add:'-1' }}{% else %}{% url 'weblog:CategoryIndex' category_slug=category.slug %}?page={{ current_page|add:'-1' }}{% endif %}{% else %}{% url 'weblog:Index' %}?page={{ current_page|add:'-1' }}{% endif %}">←</a></li>
+ {% if current_page == last_page and current_page|add:'-4' >= 1 %}
+ <li><a href="{% if category %}{% if category == 'misc' %}{% url 'weblog:CategoryIndex' category_slug='misc' %}?page={{ current_page|add:'-4' }}{% else %}{% url 'weblog:CategoryIndex' category_slug=category.slug %}?page={{ current_page|add:'-4' }}{% endif %}{% else %}{% url 'weblog:Index' %}?page={{ current_page|add:'-4' }}{% endif %}">{{ current_page|add:'-4' }}</a></li>
+ {% endif %}
+ {% if current_page|add:'1' >= last_page and current_page|add:'-3' >= 1 %}
+ <li><a href="{% if category %}{% if category == 'misc' %}{% url 'weblog:CategoryIndex' category_slug='misc' %}?page={{ current_page|add:'-3' }}{% else %}{% url 'weblog:CategoryIndex' category_slug=category.slug %}?page={{ current_page|add:'-3' }}{% endif %}{% else %}{% url 'weblog:Index' %}?page={{ current_page|add:'-3' }}{% endif %}">{{ current_page|add:'-3' }}</a></li>
+ {% endif %}
+ {% if current_page|add:'-2' >= 1 %}
+ <li><a href="{% if category %}{% if category == 'misc' %}{% url 'weblog:CategoryIndex' category_slug='misc' %}?page={{ current_page|add:'-2' }}{% else %}{% url 'weblog:CategoryIndex' category_slug=category.slug %}?page={{ current_page|add:'-2' }}{% endif %}{% else %}{% url 'weblog:Index' %}?page={{ current_page|add:'-2' }}{% endif %}">{{ current_page|add:'-2' }}</a></li>
+ {% endif %}
+ {% if current_page|add:'-1' >= 1 %}
+ <li><a href="{% if category %}{% if category == 'misc' %}{% url 'weblog:CategoryIndex' category_slug='misc' %}?page={{ current_page|add:'-1' }}{% else %}{% url 'weblog:CategoryIndex' category_slug=category.slug %}?page={{ current_page|add:'-1' }}{% endif %}{% else %}{% url 'weblog:Index' %}?page={{ current_page|add:'-1' }}{% endif %}">{{ current_page|add:'-1' }}</a></li>
+ {% endif %}
+ {% endif %}
+ <li class="active"><a href="#">{{ current_page }}</a></li>
+ {% if current_page != last_page %}
+ {% if current_page|add:'1' <= last_page %}
+ <li><a href="{% if category %}{% if category == 'misc' %}{% url 'weblog:CategoryIndex' category_slug='misc' %}?page={{ current_page|add:'1' }}{% else %}{% url 'weblog:CategoryIndex' category_slug=category.slug %}?page={{ current_page|add:'1' }}{% endif %}{% else %}{% url 'weblog:Index' %}?page={{ current_page|add:'1' }}{% endif %}">{{ current_page|add:'1' }}</a></li>
+ {% endif %}
+ {% if current_page|add:'2' <= last_page %}
+ <li><a href="{% if category %}{% if category == 'misc' %}{% url 'weblog:CategoryIndex' category_slug='misc' %}?page={{ current_page|add:'2' }}{% else %}{% url 'weblog:CategoryIndex' category_slug=category.slug %}?page={{ current_page|add:'2' }}{% endif %}{% else %}{% url 'weblog:Index' %}?page={{ current_page|add:'2' }}{% endif %}">{{ current_page|add:'2' }}</a></li>
+ {% endif %}
+ {% if current_page|add:'-1' <= 1 and current_page|add:'3' <= last_page %}
+ <li><a href="{% if category %}{% if category == 'misc' %}{% url 'weblog:CategoryIndex' category_slug='misc' %}?page={{ current_page|add:'3' }}{% else %}{% url 'weblog:CategoryIndex' category_slug=category.slug %}?page={{ current_page|add:'3' }}{% endif %}{% else %}{% url 'weblog:Index' %}?page={{ current_page|add:'3' }}{% endif %}">{{ current_page|add:'3' }}</a></li>
+ {% endif %}
+ {% if current_page == 1 and current_page|add:'4' <= last_page %}
+ <li><a href="{% if category %}{% if category == 'misc' %}{% url 'weblog:CategoryIndex' category_slug='misc' %}?page={{ current_page|add:'4' }}{% else %}{% url 'weblog:CategoryIndex' category_slug=category.slug %}?page={{ current_page|add:'4' }}{% endif %}{% else %}{% url 'weblog:Index' %}?page={{ current_page|add:'4' }}{% endif %}">{{ current_page|add:'4' }}</a></li>
+ {% endif %}
+ <li title="{% trans 'Next' context 'Page' %}"><a href="{% if category %}{% if category == 'misc' %}{% url 'weblog:CategoryIndex' category_slug='misc' %}?page={{ current_page|add:'1' }}{% else %}{% url 'weblog:CategoryIndex' category_slug=category.slug %}?page={{ current_page|add:'1' }}{% endif %}{% else %}{% url 'weblog:Index' %}?page={{ current_page|add:'1' }}{% endif %}">→</a></li>
+ <li title="{% trans 'Last' context 'Page' %}"><a href="{% if category %}{% if category == 'misc' %}{% url 'weblog:CategoryIndex' category_slug='misc' %}?page={{ last_page }}{% else %}{% url 'weblog:CategoryIndex' category_slug=category.slug %}?page={{ last_page }}{% endif %}{% else %}{% url 'weblog:Index' %}?page={{ last_page }}{% endif %}">»</a></li>
+ {% endif %}
+ </ul>
+ {% endif %}
+ {% else %}
+ <div class="text-center"><h2>{% trans 'Nothing has been posted yet.' %}</h2></div>
+ {% endif %}
+{% endblock %}
\ No newline at end of file diff --git a/weblog/templates/weblog/post.html b/weblog/templates/weblog/post.html new file mode 100644 index 0000000..364e17c --- /dev/null +++ b/weblog/templates/weblog/post.html @@ -0,0 +1,67 @@ +{% extends 'weblog/weblog.html' %} +{% load i18n %} +{% block title_block %}{% if post_translation %}{{ post_translation.title }}{% else %}{{ post.title }}{% endif %}{% endblock %} +{% block blog_content_block %} +<div class="container-fluid blogpost"> + <h2>{% if post_translation %}{{ post_translation.title }}{% else %}{{ post.title }}{% endif %}</h2> + <p class="publish-info">{% blocktrans with publish_date=post.publish_date %}Published on {{ publish_date }}{% endblocktrans %}{% if post_author %}{% blocktrans with author=post_author context 'Written by (Author)' %}, by {{ author }}{% endblocktrans %}{% endif %}</p> + <hr> + {% if post_translation %} + {{ post_translation.content|safe }} + {% else %} + {{ post.content|safe }} + {% endif %} + {% if post_categories %} + <hr> + <p>{% trans 'Categories' context 'Post categories' %}: + {% for post_category in post_categories %} + <a class="label label-info" href="{% url 'weblog:CategoryIndex' category_slug=post_category.slug %}">{{ post_category.name }}</a> + {% endfor %} + </p>{% endif %} + {% if enable_comments %} + <hr id="#comment-section"> + {% if user.is_authenticated or allow_anon_comments %} + <h3>{% trans 'Leave a comment' %}</h3> + <form id="comment_form" method="POST" action="{{ post.get_absolute_url }}#comment-section"> + {% csrf_token %} + <div class="form-group"> + {{ comment_form }} + </div> + <div class="form-group text-right"> + <button class="btn btn-primary" type="submit" value="Submit">{% trans 'Submit comment' %}</button> + </div> + </form> + {% else %} + <h4>{% trans 'To leave a comment you need to sign in' %}</h4> + {% endif %} + {% if comments %} + {% if comment_submission %} + {% if comment_submission_error %} + <div class="alert alert-danger alert-dismissable"> + <a href="#" class="close" data-dismiss="alert" aria-label="close">×</a> + {{ comment_submission_error }} + </div> + {% else %} + <div class="alert alert-success alert-dismissable"> + <a href="#" class="close" data-dismiss="alert" aria-label="close">×</a> + {% trans 'Comment submited successfully' %} + </div> + {% endif %} + {% endif %} + {% for comment in comments %} + <div class="media"> + <div class="media-body"> + <h4 class="media-heading">{% if comment.author %}{{ comment.author.get_username }}{% else %}{% trans 'Anonymous' context 'Unauthenticated comment poster' %}{% endif %}</h4> + <p>{{ comment.content }}</p> + </div> + </div> + {% endfor %} + {% else %} + <div class="text-center"> + <br> + <h3>{% trans 'Nobody has left a comment on this post yet' %}</h3> + </div> + {% endif %} + {% endif %} +</div> +{% endblock %}
\ No newline at end of file diff --git a/weblog/templates/weblog/sidebar_archive.html b/weblog/templates/weblog/sidebar_archive.html new file mode 100644 index 0000000..5953bfe --- /dev/null +++ b/weblog/templates/weblog/sidebar_archive.html @@ -0,0 +1,13 @@ +{% load i18n %} +<h3>{% trans 'Archive' context 'Blog archive' %}</h3> +<ul class='archive-list'> +{% for a_year in archive %} +<li><a class="node-toggle" node-target="{{ a_year.0 }}-list" node-state="closed" href="javascript:void(0)" onclick="toggleNode(this);">+</a> <a href="{% url 'weblog:ArchiveIndex' year=a_year.0 %}">{{ a_year.0 }}</a> + <ul id="{{ a_year.0 }}-list" class='archive-child-list'> + {% for a_month in a_year.1 %} + <li><a href="{% url 'weblog:ArchiveIndex' year=a_year.0 month=a_month.0 %}">{{ a_month.1 }}</a></li> + {% endfor %} + </ul> +</li> +{% endfor %} +</ul>
\ No newline at end of file diff --git a/weblog/templates/weblog/sidebar_categories.html b/weblog/templates/weblog/sidebar_categories.html new file mode 100644 index 0000000..7e7fa5c --- /dev/null +++ b/weblog/templates/weblog/sidebar_categories.html @@ -0,0 +1,11 @@ +{% load i18n %} +{% if categories %} +<h3>{% trans 'Categories' context 'Post categories' %}</h3> +<div class="list-group weblog-categories"> + {% for category in categories %} + <a href="{% url 'weblog:CategoryIndex' category_slug=category.slug %}" class="list-group-item{% if category.slug == selected_cat_slug %} active{% endif %}"> + {{ category.name }} + </a> + {% endfor %} +</div> +{% endif %}
\ No newline at end of file diff --git a/weblog/templates/weblog/weblog.html b/weblog/templates/weblog/weblog.html new file mode 100644 index 0000000..9980b54 --- /dev/null +++ b/weblog/templates/weblog/weblog.html @@ -0,0 +1,42 @@ +{% extends base_template %} +{% load i18n %} +{% load weblog_extras %} +{% block title_block %}{% endblock %} +{% block blog_block %} +<ol class="breadcrumb"> + {% if breadcrumbs %} + <li><a href="{% url 'weblog:Index' %}">{{ blog_title }}</a></li> + {% for crumb in breadcrumbs %} + {% if forloop.last %} + <li class="active">{{ crumb.name }}</li> + {% else %}<li><a href="{{ crumb.url }}">{{ crumb.name }}</a></li>{% endif %} + {% endfor %} + {% else %} + <li class="active"><a href="{% url 'weblog:Index' %}">{{ blog_title }}</a></li> + {% endif %} +</ol> +<div class="row"> + <div class="{% if show_sidebar %}col-sm-9{% else %}container-fluid{% endif %}"> + {% block blog_content_block %} + {% endblock %} + </div> + {% if show_sidebar %} + <div class="col-sm-3 weblog-sidebar"> + {% if show_categories %} + {% if category %} + {% if category == 'misc' %} + {% get_sidebar_categories category %} + {% else %} + {% get_sidebar_categories category.slug %} + {% endif %} + {% else %} + {% get_sidebar_categories %} + {% endif %} + {% endif %} + {% if show_archive %} + {% get_sidebar_archive %} + {% endif %} + </div> + {% endif %} +</div> +{% endblock %}
\ No newline at end of file diff --git a/weblog/templates/weblog_base.html b/weblog/templates/weblog_base.html new file mode 100644 index 0000000..536e736 --- /dev/null +++ b/weblog/templates/weblog_base.html @@ -0,0 +1,28 @@ +<!DOCTYPE html>
+{% load static %}
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Simple blog - {% block title_block %} Home {% endblock %}</title>
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
+ <link rel="stylesheet" href="{% static '/weblog/css/weblog.css' %}">
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" defer></script>
+ <script src="{% static '/weblog/js/weblog.js' %}" defer></script>
+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" defer></script>
+ </head>
+ <body>
+ <nav class="navbar navbar-inverse">
+ <div class="container nav-container">
+ <div class="navbar-header">
+ <a class="navbar-brand" href="{% url 'weblog:Index' %}">{{ blog_title }}</a>
+ </div>
+ </div>
+ </nav>
+ <div class="container">
+ {% block content_block %}
+ {% block blog_block %}
+ {% endblock %}
+ {% endblock %}
+ </div>
+ </body>
+</html>
\ No newline at end of file diff --git a/weblog/templates/weblog_base_old.html b/weblog/templates/weblog_base_old.html new file mode 100644 index 0000000..a4dbd30 --- /dev/null +++ b/weblog/templates/weblog_base_old.html @@ -0,0 +1,35 @@ +<!DOCTYPE html>
+{% load static %}
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Simple blog - {% block title_block %} Home {% endblock %}</title>
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
+ <link rel="stylesheet" href="{% static '/weblog/css/weblog.css' %}">
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" defer></script>
+ <script src="{% static '/weblog/js/weblog.js' %}" defer></script>
+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" defer></script>
+ </head>
+ <body>
+ <nav class="navbar navbar-inverse">
+ <div class="container nav-container">
+ <div class="navbar-header">
+ <a class="navbar-brand" href="{% url 'weblog:Index' %}">{{ blog_title }}</a>
+ </div>
+ <div class="collapse navbar-collapse">
+ <ul class="nav navbar-nav navbar-right">
+ <li><a href="{% url 'weblog:ChangeLanguage' language='en' %}?next={{ request.path }}">EN</a></li>
+ <li><a href="{% url 'weblog:ChangeLanguage' language='es' %}?next={{ request.path }}">ES</a></li>
+ <li><a href="{% url 'weblog:ChangeLanguage' language='ru' %}?next={{ request.path }}">RU</a></li>
+ </ul>
+ </div>
+ </div>
+ </nav>
+ <div class="container">
+ {% block content_block %}
+ {% block blog_block %}
+ {% endblock %}
+ {% endblock %}
+ </div>
+ </body>
+</html>
\ No newline at end of file diff --git a/weblog/templatetags/__init__.py b/weblog/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/weblog/templatetags/__init__.py diff --git a/weblog/templatetags/__pycache__/__init__.cpython-35.pyc b/weblog/templatetags/__pycache__/__init__.cpython-35.pyc Binary files differnew file mode 100644 index 0000000..8b2440b --- /dev/null +++ b/weblog/templatetags/__pycache__/__init__.cpython-35.pyc diff --git a/weblog/templatetags/__pycache__/__init__.cpython-36.pyc b/weblog/templatetags/__pycache__/__init__.cpython-36.pyc Binary files differnew file mode 100644 index 0000000..8ec5021 --- /dev/null +++ b/weblog/templatetags/__pycache__/__init__.cpython-36.pyc diff --git a/weblog/templatetags/__pycache__/weblog_extras.cpython-35.pyc b/weblog/templatetags/__pycache__/weblog_extras.cpython-35.pyc Binary files differnew file mode 100644 index 0000000..bcc8327 --- /dev/null +++ b/weblog/templatetags/__pycache__/weblog_extras.cpython-35.pyc diff --git a/weblog/templatetags/__pycache__/weblog_extras.cpython-36.pyc b/weblog/templatetags/__pycache__/weblog_extras.cpython-36.pyc Binary files differnew file mode 100644 index 0000000..eb1b1e6 --- /dev/null +++ b/weblog/templatetags/__pycache__/weblog_extras.cpython-36.pyc diff --git a/weblog/templatetags/weblog_extras.py b/weblog/templatetags/weblog_extras.py new file mode 100644 index 0000000..1f72a86 --- /dev/null +++ b/weblog/templatetags/weblog_extras.py @@ -0,0 +1,70 @@ +from django import template +from django.utils import translation +from django.utils.translation import ugettext_lazy as _, pgettext_lazy +from django.conf import settings +from weblog.apps import SETTINGS as blog_settings +from weblog.models import Category, CategoryTranslation, BlogPost +import datetime + +IS_MULTILINGUAL = blog_settings['multilingual'] + +MONTHS = ( + _('January'), + _('February'), + _('March'), + _('April'), + _('May'), + _('June'), + _('July'), + _('August'), + _('September'), + _('October'), + _('November'), + _('December'), +) + +register = template.Library() + +@register.inclusion_tag('weblog/sidebar_categories.html') +def get_sidebar_categories(selected_cat_slug=None): + now = datetime.datetime.now() + current_language = translation.get_language() + if current_language is None: + current_language = settings.LANGUAGE_CODE + context_dict = {'categories': [], 'selected_cat_slug': selected_cat_slug} + for raw_category in Category.objects.all(): + next_category = {'name': raw_category.name, 'slug': raw_category.slug} + if CategoryTranslation.objects.filter(category=raw_category).count() > 0 and IS_MULTILINGUAL: + for category_translation in CategoryTranslation.objects.filter(category=raw_category): + if current_language[0:2] == category_translation.language[0:2]: + next_category['name'] = category_translation.name + context_dict['categories'].append(next_category) + if BlogPost.objects.filter(published=True, publish_date__lte=now, categories=None).count() > 0: + context_dict['categories'].append({'name': pgettext_lazy('Posts without category', 'Uncategorized'), 'slug': 'misc'}) + return context_dict + + +@register.inclusion_tag('weblog/sidebar_archive.html') +def get_sidebar_archive(): + now = datetime.datetime.now() + oldest_post = BlogPost.objects.filter(published=True).reverse()[0] + first_year = oldest_post.publish_date.year + first_month = oldest_post.publish_date.month + newest_post = BlogPost.objects.filter(published=True, publish_date__lte=now)[0] + latest_year = newest_post.publish_date.year + latest_month = newest_post.publish_date.month + c_month = first_month + c_year = first_year + archive = [] + while c_year <= latest_year: + if BlogPost.objects.filter(publish_date__year=c_year, publish_date__lte=now, published=True).count() > 0: + this_years_months = [] + while (c_year < latest_year or c_month <= latest_month) and c_month <= 12: + if BlogPost.objects.filter(publish_date__month=c_month, publish_date__lte=now, published=True).count() > 0: + this_years_months.append((c_month, MONTHS[c_month-1])) + c_month+=1 + archive.append((c_year, this_years_months)) + c_year+=1 + c_month=1 + archive.reverse() + return {'archive': archive} diff --git a/weblog/tests.py b/weblog/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/weblog/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/weblog/urls.py b/weblog/urls.py new file mode 100644 index 0000000..643e8c7 --- /dev/null +++ b/weblog/urls.py @@ -0,0 +1,12 @@ +from django.conf.urls import url
+from . import views
+
+app_name = 'weblog'
+urlpatterns = [
+ url(r'^$', views.Index, name='Index'),
+ url(r'^change-language/(?P<language>[-\w]+)/$', views.ChangeLanguage, name='ChangeLanguage'),
+ url(r'^(?P<year>[0-9]{4})/$', views.Index, name='ArchiveIndex'),
+ url(r'^(?P<year>[0-9]{4})/(?P<month>[0-9]{1,2})/$', views.Index, name='ArchiveIndex'),
+ url(r'^(?P<category_slug>[-\w]+)/$', views.Index, name='CategoryIndex'),
+ url(r'^(?P<category_slug>[-\w]+)/(?P<post_slug>[-\w]+)/$', views.PostView, name='PostView'),
+]
\ No newline at end of file diff --git a/weblog/views.py b/weblog/views.py new file mode 100644 index 0000000..8a05bcc --- /dev/null +++ b/weblog/views.py @@ -0,0 +1,207 @@ +from django.shortcuts import render, get_object_or_404, redirect, reverse +from django.http import Http404, HttpResponseRedirect +from django.conf import settings +from django.utils import translation +from django.utils.translation import ugettext_lazy as _, pgettext_lazy +from .apps import SETTINGS as blog_settings +from .models import BlogPost, Translation, PostComment, Category, CategoryTranslation, PostCommentForm +import datetime + +#Why the hell didn't I just pass the variables to the context_dict in the first place?? +#Need to remove this later +IS_MULTILINGUAL = blog_settings['multilingual'] +BASE_TEMPLATE = blog_settings['base_template'] +BLOG_TITLE = blog_settings['blog_title'] +SHOW_SIDEBAR = blog_settings['show_sidebar'] +POSTS_PER_PAGE = blog_settings['posts_per_page'] +SHOW_AUTHOR = blog_settings['show_author'] +USE_AUTHORS_USERNAME = blog_settings['use_authors_username'] +ENABLE_COMMENTS = blog_settings['enable_comments'] +ALLOW_ANON_COMMENTS = blog_settings['allow_anon_comments'] + +def Index(request, **kwargs): + context_dict = blog_settings.copy() + now = datetime.datetime.now() + all_pages = BlogPost.objects.filter(published=True, publish_date__lte=now) + category = None + if kwargs is not None: + category_slug = kwargs.get('category_slug') + year = kwargs.get('year') + month = kwargs.get('month') + if category_slug: + if category_slug == 'misc': + all_pages = BlogPost.objects.filter(published=True, publish_date__lte=now, categories=None) + context_dict['category'] = 'misc' + else: + category = get_object_or_404(Category, slug=category_slug) + context_dict['category'] = category + all_pages = BlogPost.objects.filter(published=True, publish_date__lte=now, categories__slug=category_slug) + if year: + all_pages = BlogPost.objects.filter(published=True, publish_date__lte=now, publish_date__year=year) + if month: + all_pages = BlogPost.objects.filter(published=True, publish_date__lte=now, publish_date__month=month) + post_count = all_pages.count() + if post_count < 1: + return render(request, 'weblog/index.html', context_dict) + page = 0 + if request.GET.get('page'): + page = int(request.GET['page'])-1 + if page * POSTS_PER_PAGE + 1 > post_count: + page = 0 + context_dict['current_page'] = page+1 + slice_start = page*POSTS_PER_PAGE + slice_end = page*POSTS_PER_PAGE + POSTS_PER_PAGE + if slice_end >= post_count: + slice_end = post_count + if post_count % POSTS_PER_PAGE == 0: + last_page = int(post_count/POSTS_PER_PAGE) + else: + last_page = int(post_count/POSTS_PER_PAGE)+1 + context_dict['last_page'] = last_page + posts_raw = all_pages[slice_start:slice_end] + if category_slug: + posts_raw = all_pages[slice_start:slice_end] + current_language = translation.get_language() + if current_language is None: + current_language = settings.LANGUAGE_CODE + if category_slug: + if IS_MULTILINGUAL and category_slug != 'misc': + category_translations = CategoryTranslation.objects.filter(category=category) + if category_translations.count() > 0: + for cat_trans in category_translations: + if current_language[0:2] == cat_trans.language[0:2]: + context_dict['category'] = cat_trans + if category_slug == 'misc': + context_dict['breadcrumbs'] = [{'url': reverse('weblog:CategoryIndex', kwargs={'category_slug': category_slug}), 'name': pgettext_lazy('Posts without category', 'Uncategorized')},] + else: + context_dict['breadcrumbs'] = [{'url': reverse('weblog:CategoryIndex', kwargs={'category_slug': category_slug}), 'name': context_dict['category']},] + posts = [] + for post_raw in posts_raw: + post = {'publish_date': post_raw.publish_date, 'url': post_raw.get_absolute_url()} + if SHOW_AUTHOR: + post['author'] = post_raw.author.get_full_name() + if USE_AUTHORS_USERNAME: + post['author'] = post_raw.author.get_username() + translation_exists = False + post_translations = Translation.objects.filter(post=post_raw) + if post_translations.count() < 1 or not IS_MULTILINGUAL: + post['title'] = post_raw.title + post['content'] = post_raw.content + post['preview_image'] = post_raw.preview_image + if len(post_raw.preview_text) > 5: + post['preview_text'] = post_raw.preview_text + else: + post['preview_text'] = post_raw.content.split('</p>', 1)[0]+'</p>' + else: + post_trans = None + orig_lang = post_raw.original_language + if len(orig_lang) < 2: + orig_lang = settings.LANGUAGE_CODE[0:2] + post['languages'] = [orig_lang,] + for post_translation in post_translations: + post['languages'].append(post_translation.language) + if current_language[0:2] == post_translation.language[0:2]: + post_trans = post_translation + if post_trans: + post['title'] = post_trans.title + post['content'] = post_trans.content + post['current_language'] = post_trans.language + post['preview_image'] = post_trans.preview_image + if len(post_trans.preview_text) > 5: + post['preview_text'] = post_trans.preview_text + else: + post['preview_text'] = post_trans.content.split('\n', 1)[0]+'</p>' + else: + post['title'] = post_raw.title + post['content'] = post_raw.content + post['current_language'] = orig_lang + post['preview_image'] = post_raw.preview_image + if len(post_raw.preview_text) > 5: + post['preview_text'] = post_raw.preview_text + else: + post['preview_text'] = post_raw.content.split('</p>', 1)[0]+'</p>' + posts.append(post) + context_dict['posts'] = posts + return render(request, 'weblog/index.html', context_dict) + + +def PostView(request, category_slug, post_slug): + post = get_object_or_404(BlogPost, slug=post_slug) + context_dict = blog_settings.copy() + context_dict['comment_form'] = PostCommentForm() + post_translations = Translation.objects.filter(post=post) + category = None + current_language = translation.get_language() + if current_language is None: + current_language = settings.LANGUAGE_CODE + if category_slug: + if category_slug == 'misc': + context_dict['category'] = 'misc' + else: + category = get_object_or_404(Category, slug=category_slug) + context_dict['category'] = category + if IS_MULTILINGUAL: + category_translations = CategoryTranslation.objects.filter(category=category) + if category_translations.count() > 0: + for cat_trans in category_translations: + if current_language[0:2] == cat_trans.language[0:2]: + context_dict['category'] = cat_trans + if category_slug == 'misc': + context_dict['breadcrumbs'] = [{'url': reverse('weblog:CategoryIndex', kwargs={'category_slug': category_slug}), 'name': pgettext_lazy('Posts without category', 'Uncategorized')},] + else: + context_dict['breadcrumbs'] = [{'url': reverse('weblog:CategoryIndex', kwargs={'category_slug': category_slug}), 'name': context_dict['category']},] + if SHOW_AUTHOR: + context_dict['post_author'] = post.author.get_full_name() + if USE_AUTHORS_USERNAME: + context_dict['post_author'] = post.author.get_username() + if ENABLE_COMMENTS: + context_dict['comments'] = PostComment.objects.filter(post=post) + if request.method == 'POST': + form = PostCommentForm(request.POST) + context_dict['comment_submission'] = True + if form.is_valid(): + comment_content = form.cleaned_data['content'] + if request.user.is_authenticated(): + new_comment = PostComment(author=request.user, post=post, content=comment_content) + new_comment.save() + elif ALLOW_ANON_COMMENTS: + new_comment = PostComment(post=post, content=comment_content) + new_comment.save() + else: + context_dict['comment_submission_error'] = _('You need to sign in to submit a comment') + else: + context_dict['comment_submission_error'] = _('Error submitting comment: Invalid data') + context_dict['post'] = post + if post.categories.all().count() > 0: + context_dict['post_categories'] = [] + for raw_category in post.categories.all(): + next_category = {'name': raw_category.name, 'slug': raw_category.slug} + if CategoryTranslation.objects.filter(category=raw_category).count() > 0 and IS_MULTILINGUAL: + for category_translation in CategoryTranslation.objects.filter(category=raw_category): + if current_language[0:2] == category_translation.language[0:2]: + next_category['name'] = category_translation.name + context_dict['post_categories'].append(next_category) + if post_translations.count() < 1 or not IS_MULTILINGUAL: + context_dict['breadcrumbs'].append({'url': post.get_absolute_url(), 'name': post.title}) + return render(request, 'weblog/post.html', context_dict) + orig_lang = post.original_language + if len(orig_lang) < 2: + orig_lang = settings.LANGUAGE_CODE[0:2] + context_dict['languages'] = [orig_lang,] + for post_translation in post_translations: + context_dict['languages'].append(post_translation.language) + if current_language[0:2] == post_translation.language[0:2]: + context_dict['post_translation'] = post_translation + if 'post_translation' in context_dict: + context_dict['breadcrumbs'].append({'url': post.get_absolute_url(), 'name': post_translation.title}) + else: + context_dict['breadcrumbs'].append({'url': post.get_absolute_url(), 'name': post.title}) + return render(request, 'weblog/post.html', context_dict) + +def ChangeLanguage(request, language): + translation.activate(language) + request.session[translation.LANGUAGE_SESSION_KEY] = language + if request.GET.get('next'): + return HttpResponseRedirect(request.GET['next']) + return HttpResponseRedirect(reverse('weblog:Index')) +
\ No newline at end of file |