fix a typo, update admin base classes

This commit is contained in:
Tadas Dailyda 2014-11-30 21:56:50 +00:00
commit 7f534c90df
34 changed files with 1366 additions and 280 deletions

View file

@ -12,6 +12,7 @@ env:
matrix: matrix:
- DJANGO='django>=1.5,<1.6' NOSE_COVER_PACKAGE="djangocms_blog" NOSE_WITH_COVERAGE=1 - DJANGO='django>=1.5,<1.6' NOSE_COVER_PACKAGE="djangocms_blog" NOSE_WITH_COVERAGE=1
- DJANGO='django>=1.6,<1.7' NOSE_COVER_PACKAGE="djangocms_blog" NOSE_WITH_COVERAGE=1 - DJANGO='django>=1.6,<1.7' NOSE_COVER_PACKAGE="djangocms_blog" NOSE_WITH_COVERAGE=1
- DJANGO='django>=1.7,<1.8' NOSE_COVER_PACKAGE="djangocms_blog" NOSE_WITH_COVERAGE=1
# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors # command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors
install: install:
@ -24,13 +25,22 @@ script: djangocms-helper djangocms_blog test --cms --nose-runner
after_success: coveralls after_success: coveralls
matrix: matrix:
exclude:
- python: 2.6
env: DJANGO='django>=1.7,<1.8' NOSE_COVER_PACKAGE="djangocms_blog" NOSE_WITH_COVERAGE=1
allow_failures: allow_failures:
- python: 2.7
env: DJANGO='django>=1.7,<1.8' NOSE_COVER_PACKAGE="djangocms_blog" NOSE_WITH_COVERAGE=1
- python: 3.3 - python: 3.3
env: DJANGO='django>=1.5,<1.6' NOSE_COVER_PACKAGE="djangocms_blog" NOSE_WITH_COVERAGE=1 env: DJANGO='django>=1.5,<1.6' NOSE_COVER_PACKAGE="djangocms_blog" NOSE_WITH_COVERAGE=1
- python: 3.3 - python: 3.3
env: DJANGO='django>=1.6,<1.7' NOSE_COVER_PACKAGE="djangocms_blog" NOSE_WITH_COVERAGE=1 env: DJANGO='django>=1.6,<1.7' NOSE_COVER_PACKAGE="djangocms_blog" NOSE_WITH_COVERAGE=1
- python: 3.3
end: DJANGO='django>=1.7,<1.8' NOSE_COVER_PACKAGE="djangocms_blog" NOSE_WITH_COVERAGE=1
- python: 3.4 - python: 3.4
env: DJANGO='django>=1.5,<1.6' NOSE_COVER_PACKAGE="djangocms_blog" NOSE_WITH_COVERAGE=1 env: DJANGO='django>=1.5,<1.6' NOSE_COVER_PACKAGE="djangocms_blog" NOSE_WITH_COVERAGE=1
- python: 3.4 - python: 3.4
env: DJANGO='django>=1.6,<1.7' NOSE_COVER_PACKAGE="djangocms_blog" NOSE_WITH_COVERAGE=1 env: DJANGO='django>=1.6,<1.7' NOSE_COVER_PACKAGE="djangocms_blog" NOSE_WITH_COVERAGE=1
- python: 3.4
env: DJANGO='django>=1.7,<1.8' NOSE_COVER_PACKAGE="djangocms_blog" NOSE_WITH_COVERAGE=1

View file

@ -3,6 +3,14 @@
History History
------- -------
0.3.0 (Unreleased)
++++++++++++++++++
* Multisite support
* Configurable default author support
* Refactored settings
* Fix multilanguage issues
0.2.0 (2014-09-24) 0.2.0 (2014-09-24)
++++++++++++++++++ ++++++++++++++++++

View file

@ -3,4 +3,4 @@ include CONTRIBUTING.rst
include HISTORY.rst include HISTORY.rst
include LICENSE include LICENSE
include README.rst include README.rst
recursive-include djangocms_blog *.html *.png *.gif *js *jpg *jpeg *svg *py *css recursive-include djangocms_blog *.html *.png *.gif *js *jpg *jpeg *svg *py *css *po *mo

View file

@ -45,7 +45,7 @@ Quickstart
Install djangocms-blog:: Install djangocms-blog::
pip install djangocms-blog==0.2c1 pip install djangocms-blog
Add ``djangocms_blog`` and its dependencies to INSTALLED_APPS:: Add ``djangocms_blog`` and its dependencies to INSTALLED_APPS::
@ -142,6 +142,7 @@ Features
* Multilingual support using django-parler * Multilingual support using django-parler
* Support for Twitter cards, Open Graph and Google+ snippets meta tags * Support for Twitter cards, Open Graph and Google+ snippets meta tags
* Optional support for simpler TextField-based content editing * Optional support for simpler TextField-based content editing
* Multisite support (posts can be visible in one or more Django sites on the same project)
Import from Wordpress Import from Wordpress
+++++++++++++++++++++ +++++++++++++++++++++
@ -154,19 +155,24 @@ this gist https://gist.github.com/yakky/11336204 as a base.
Settings Settings
-------- --------
* BLOG_ENABLE_COMMENTS: Whether to enable comments by default on posts; * BLOG_ENABLE_COMMENTS: Whether to enable comments by default on posts;
while `djangocms_blog` does not ship any comment system, this flag can be used while ``djangocms_blog`` does not ship any comment system, this flag can be used
to control the chosen comments framework; (default: True) to control the chosen comments framework; (default: True)
* BLOG_USE_PLACEHOLDER: Post content is managed via placeholder; if `False` a * BLOG_USE_PLACEHOLDER: Post content is managed via placeholder; if ``False`` a
simple HTMLField is used; (default: True) simple HTMLField is used; (default: True)
* BLOG_IMAGE_THUMBNAIL_SIZE: Size of the main image when shown on the post lists; * BLOG_IMAGE_THUMBNAIL_SIZE: Size of the main image when shown on the post lists;
it's a dictionary with `size`, `crop` and `upscale` keys; it's a dictionary with ``size``, ``crop`` and ``upscale`` keys;
(default: `{'size': '120x120', 'crop': True,'upscale': False}`) (default: ``{'size': '120x120', 'crop': True,'upscale': False}``)
* BLOG_IMAGE_FULL_SIZE: Size of the main image when shown on the post detail; * BLOG_IMAGE_FULL_SIZE: Size of the main image when shown on the post detail;
it's a dictionary with `size`, `crop` and `upscale` keys; it's a dictionary with ``size``, ``crop`` and ``upscale`` keys;
(default: `{'size': '640x120', 'crop': True,'upscale': False}`) (default: ``{'size': '640x120', 'crop': True,'upscale': False}``)
* BLOG_PAGINATION: Number of post per page; (defaul: 10) * BLOG_PAGINATION: Number of post per page; (default: 10)
* BLOG_LATEST_POSTS: Default number of post in the **Latest post** plugin; (defaul: 5) * BLOG_LATEST_POSTS: Default number of post in the **Latest post** plugin; (default: 5)
* BLOG_POSTS_LIST_TRUNCWORDS_COUNT: Default number of words shown for abstract in the post list; (default: 100) * BLOG_POSTS_LIST_TRUNCWORDS_COUNT: Default number of words shown for abstract in the post list; (default: 100)
* BLOG_MULTISITE: Add support for multisite setup
* BLOG_AUTHOR_DEFAULT: Use a default if not specified; if set to ``True`` the
current user is set as the default author, if set to ``False`` no default
author is set, if set to a string the user with the provided username is
used; (default: True)
Social media tags settings Social media tags settings
++++++++++++++++++++++++++ ++++++++++++++++++++++++++

View file

@ -9,6 +9,7 @@ HELPER_SETTINGS = {
], ],
'ROOT_URLCONF': 'tests.test_utils.urls', 'ROOT_URLCONF': 'tests.test_utils.urls',
'INSTALLED_APPS': [ 'INSTALLED_APPS': [
'django.contrib.messages',
'admin_enhancer', 'admin_enhancer',
'filer', 'filer',
'parler', 'parler',
@ -46,6 +47,13 @@ HELPER_SETTINGS = {
'public': True, 'public': True,
}, },
], ],
2: [
{
'code': 'en',
'name': gettext('English'),
'public': True,
},
],
'default': { 'default': {
'hide_untranslated': False, 'hide_untranslated': False,
}, },
@ -56,11 +64,17 @@ HELPER_SETTINGS = {
{'code': 'it'}, {'code': 'it'},
{'code': 'fr'}, {'code': 'fr'},
), ),
2: (
{'code': 'en'},
),
'default': { 'default': {
'fallback': 'en', 'fallback': 'en',
'hide_untranslated': False, 'hide_untranslated': False,
} }
}, },
'MIDDLEWARE_CLASSES': [
'django.contrib.messages.middleware.MessageMiddleware',
],
'META_SITE_PROTOCOL': 'http', 'META_SITE_PROTOCOL': 'http',
'META_SITE_DOMAIN': 'example.com', 'META_SITE_DOMAIN': 'example.com',
'META_USE_OG_PROPERTIES': True, 'META_USE_OG_PROPERTIES': True,
@ -73,6 +87,7 @@ HELPER_SETTINGS = {
'easy_thumbnails.processors.filters', 'easy_thumbnails.processors.filters',
), ),
'FILE_UPLOAD_TEMP_DIR': mkdtemp(), 'FILE_UPLOAD_TEMP_DIR': mkdtemp(),
'SITE_ID': 1
} }
if 'test' in sys.argv: if 'test' in sys.argv:
HELPER_SETTINGS['INSTALLED_APPS'].append('django_nose') HELPER_SETTINGS['INSTALLED_APPS'].append('django_nose')

View file

@ -1 +1 @@
__version__ = '0.2' __version__ = '0.3.a4'

View file

@ -4,10 +4,11 @@ from cms.admin.placeholderadmin import PlaceholderAdminMixin, FrontendEditableAd
from copy import deepcopy from copy import deepcopy
from django.contrib import admin from django.contrib import admin
from django.conf import settings from django.conf import settings
from django.contrib.auth import get_user_model
from parler.admin import TranslatableAdmin from parler.admin import TranslatableAdmin
from .models import Post, BlogCategory from .models import Post, BlogCategory
from .settings import BLOG_USE_PLACEHOLDER from .settings import get_setting
class BlogCategoryAdmin(EnhancedModelAdminMixin, TranslatableAdmin): class BlogCategoryAdmin(EnhancedModelAdminMixin, TranslatableAdmin):
@ -49,8 +50,10 @@ class PostAdmin(EnhancedModelAdminMixin, FrontendEditableAdminMixin,
def get_fieldsets(self, request, obj=None): def get_fieldsets(self, request, obj=None):
fsets = deepcopy(self._fieldsets) fsets = deepcopy(self._fieldsets)
if not BLOG_USE_PLACEHOLDER: if not get_setting('USE_PLACEHOLDER'):
fsets[0][1]['fields'].append('post_text') fsets[0][1]['fields'].append('post_text')
if get_setting('MULTISITE'):
fsets[1][1]['fields'][0].append('sites')
if request.user.is_superuser: if request.user.is_superuser:
fsets[1][1]['fields'][0].append('author') fsets[1][1]['fields'][0].append('author')
return fsets return fsets
@ -59,8 +62,12 @@ class PostAdmin(EnhancedModelAdminMixin, FrontendEditableAdminMixin,
return {'slug': ('title',)} return {'slug': ('title',)}
def save_model(self, request, obj, form, change): def save_model(self, request, obj, form, change):
if not obj.author_id: if not obj.author_id and get_setting('AUTHOR_DEFAULT'):
obj.author = request.user if get_setting('AUTHOR_DEFAULT') is True:
user = request.user
else:
user = get_user_model().objects.get(username=get_setting('AUTHOR_DEFAULT'))
obj.author = user
super(PostAdmin, self).save_model(request, obj, form, change) super(PostAdmin, self).save_model(request, obj, form, change)
class Media: class Media:

View file

@ -7,7 +7,7 @@ from cms.plugin_pool import plugin_pool
from .models import AuthorEntriesPlugin, LatestPostsPlugin, Post, BlogCategory from .models import AuthorEntriesPlugin, LatestPostsPlugin, Post, BlogCategory
from .forms import LatestEntriesForm from .forms import LatestEntriesForm
from .settings import BLOG_POSTS_LIST_TRUNCWORDS_COUNT from .settings import get_setting
class BlogPlugin(CMSPluginBase): class BlogPlugin(CMSPluginBase):
@ -24,7 +24,7 @@ class BlogLatestEntriesPlugin(BlogPlugin):
def render(self, context, instance, placeholder): def render(self, context, instance, placeholder):
context['instance'] = instance context['instance'] = instance
context['TRUNCWORDS_COUNT'] = BLOG_POSTS_LIST_TRUNCWORDS_COUNT context['TRUNCWORDS_COUNT'] = get_setting('POSTS_LIST_TRUNCWORDS_COUNT')
return context return context

View file

@ -2,13 +2,14 @@
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the PACKAGE package.
# #
# Translators: # Translators:
# Bashar Al-Abdulhadi, 2014
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: djangocms-blog\n" "Project-Id-Version: djangocms-blog\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-09-01 07:16+0200\n" "POT-Creation-Date: 2014-09-01 07:16+0200\n"
"PO-Revision-Date: 2014-03-29 15:29+0000\n" "PO-Revision-Date: 2014-10-12 12:01+0000\n"
"Last-Translator: Iacopo Spalletti\n" "Last-Translator: Bashar Al-Abdulhadi\n"
"Language-Team: Arabic (http://www.transifex.com/projects/p/djangocms-blog/language/ar/)\n" "Language-Team: Arabic (http://www.transifex.com/projects/p/djangocms-blog/language/ar/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@ -20,45 +21,45 @@ msgstr ""
#: cms_app.py:8 cms_plugins.py:32 cms_plugins.py:45 cms_plugins.py:56 #: cms_app.py:8 cms_plugins.py:32 cms_plugins.py:45 cms_plugins.py:56
#: cms_plugins.py:67 cms_toolbar.py:18 #: cms_plugins.py:67 cms_toolbar.py:18
msgid "Blog" msgid "Blog"
msgstr "" msgstr "المدونة"
#: cms_plugins.py:20 #: cms_plugins.py:20
msgid "Latest Blog Articles" msgid "Latest Blog Articles"
msgstr "" msgstr "آخر مواضيع المدونة"
#: cms_plugins.py:33 #: cms_plugins.py:33
msgid "Author Blog Articles" msgid "Author Blog Articles"
msgstr "" msgstr "ناشر مواضيع المدونة"
#: cms_plugins.py:46 templates/djangocms_blog/plugins/tags.html:4 #: cms_plugins.py:46 templates/djangocms_blog/plugins/tags.html:4
msgid "Tags" msgid "Tags"
msgstr "" msgstr "علامات"
#: cms_plugins.py:57 templates/djangocms_blog/plugins/categories.html:4 #: cms_plugins.py:57 templates/djangocms_blog/plugins/categories.html:4
msgid "Categories" msgid "Categories"
msgstr "" msgstr "الأقسام"
#: cms_plugins.py:68 templates/djangocms_blog/post_list.html:12 #: cms_plugins.py:68 templates/djangocms_blog/post_list.html:12
#: templates/djangocms_blog/plugins/archive.html:4 #: templates/djangocms_blog/plugins/archive.html:4
msgid "Archive" msgid "Archive"
msgstr "" msgstr "الأرشيف"
#: cms_toolbar.py:20 #: cms_toolbar.py:20
msgid "Post list" msgid "Post list"
msgstr "" msgstr "قائمة المواضيع"
#: cms_toolbar.py:22 #: cms_toolbar.py:22
msgid "Add post" msgid "Add post"
msgstr "" msgstr "إضافة موضوع"
#: cms_toolbar.py:26 #: cms_toolbar.py:26
msgid "Edit Post" msgid "Edit Post"
msgstr "" msgstr "التعديل على موضوع"
#: feeds.py:16 #: feeds.py:16
#, python-format #, python-format
msgid "Blog articles on %(site_name)s" msgid "Blog articles on %(site_name)s"
msgstr "" msgstr "مواضيع المدونة على %(site_name)s"
#: models.py:28 #: models.py:28
msgid "parent" msgid "parent"

Binary file not shown.

View file

@ -0,0 +1,257 @@
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
# Christoph Reimers <christoph@superservice-international.com>, 2014
msgid ""
msgstr ""
"Project-Id-Version: djangocms-blog\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-09-01 07:16+0200\n"
"PO-Revision-Date: 2014-11-20 14:53+0000\n"
"Last-Translator: Christoph Reimers <christoph@superservice-international.com>\n"
"Language-Team: German (http://www.transifex.com/projects/p/djangocms-blog/language/de/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Lokalize 1.5\n"
#: cms_app.py:8 cms_plugins.py:32 cms_plugins.py:45 cms_plugins.py:56
#: cms_plugins.py:67 cms_toolbar.py:18
msgid "Blog"
msgstr "Blog"
#: cms_plugins.py:20
msgid "Latest Blog Articles"
msgstr "Letzte Blog-Einträge"
#: cms_plugins.py:33
msgid "Author Blog Articles"
msgstr "Autoren Blog-Artikel"
#: cms_plugins.py:46 templates/djangocms_blog/plugins/tags.html:4
msgid "Tags"
msgstr "Tags"
#: cms_plugins.py:57 templates/djangocms_blog/plugins/categories.html:4
msgid "Categories"
msgstr "Kategorien"
#: cms_plugins.py:68 templates/djangocms_blog/post_list.html:12
#: templates/djangocms_blog/plugins/archive.html:4
msgid "Archive"
msgstr "Archiv"
#: cms_toolbar.py:20
msgid "Post list"
msgstr "Post Liste"
#: cms_toolbar.py:22
msgid "Add post"
msgstr "Post hinzufügen"
#: cms_toolbar.py:26
msgid "Edit Post"
msgstr "Post bearbeiten"
#: feeds.py:16
#, python-format
msgid "Blog articles on %(site_name)s"
msgstr "Blog-Artikel auf %(site_name)s"
#: models.py:28
msgid "parent"
msgstr "übergeordnetes Element"
#: models.py:30
msgid "created at"
msgstr "erstellt am"
#: models.py:31
msgid "modified at"
msgstr "bearbeitet am"
#: models.py:34
msgid "name"
msgstr "Name"
#: models.py:35 models.py:95
msgid "slug"
msgstr ""
#: models.py:42
msgid "blog category"
msgstr "Blog-Kategorie"
#: models.py:43
msgid "blog categories"
msgstr "Blog-Kategorien"
#: models.py:66
msgid "Author"
msgstr "Autor"
#: models.py:71
msgid "Published Since"
msgstr "Veröffentlicht seit"
#: models.py:73
msgid "Published Until"
msgstr "Veröffentlicht bis"
#: models.py:75
msgid "Publish"
msgstr "Veröffentlichen"
#: models.py:76
msgid "category"
msgstr "Kategorie"
#: models.py:78
msgid "Main image"
msgstr "Haupt-Bild"
#: models.py:81
msgid "Main image thumbnail"
msgstr "Haupt-Bild Vorschau"
#: models.py:85
msgid "Main image full"
msgstr "volles Haupt-Bild"
#: models.py:89
msgid "Enable comments on post"
msgstr "Kommentare einschalten"
#: models.py:94
msgid "Title"
msgstr "Titel"
#: models.py:96
msgid "Abstract"
msgstr "Auszug"
#: models.py:97
msgid "Post meta description"
msgstr "Post Meta-Description"
#: models.py:99
msgid "Post meta keywords"
msgstr "Post Meta-Keywords"
#: models.py:101
msgid "Text"
msgstr "Text"
#: models.py:158
msgid "blog article"
msgstr "Blog-Artikel"
#: models.py:159
msgid "blog articles"
msgstr "Blog-Artikel"
#: models.py:199 models.py:226
msgid "Articles"
msgstr "Artikel"
#: models.py:200
msgid "The number of latests articles to be displayed."
msgstr "Anzahl der anzuzeigenden letzten Artikel"
#: models.py:202
msgid "Show only the blog articles tagged with chosen tags."
msgstr "Nur die Blog-Einträge mit dem ausgewählten Tag anzeigen"
#: models.py:204
msgid "Show only the blog articles tagged with chosen categories."
msgstr "Nur die Blog-Einträge der ausgewählten Kategorie anzeigen"
#: models.py:222 templates/djangocms_blog/plugins/authors.html:3
msgid "Authors"
msgstr "Authoren"
#: models.py:227
msgid "The number of author articles to be displayed."
msgstr "Die Anzahl der anzuzeigenden Autoren-Artikel"
#: templates/djangocms_blog/post_detail.html:16
#: templates/djangocms_blog/includes/blog_item.html:10
msgid "by"
msgstr "von"
#: templates/djangocms_blog/post_list.html:11
msgid "Articles by"
msgstr "Artikel von"
#: templates/djangocms_blog/post_list.html:13
msgid "Tag"
msgstr "Tag"
#: templates/djangocms_blog/post_list.html:14
msgid "Category"
msgstr "Kategorie"
#: templates/djangocms_blog/post_list.html:21
#: templates/djangocms_blog/plugins/archive.html:27
#: templates/djangocms_blog/plugins/authors.html:15
#: templates/djangocms_blog/plugins/categories.html:16
#: templates/djangocms_blog/plugins/latest_entries.html:7
#: templates/djangocms_blog/plugins/tags.html:16
msgid "No article found."
msgstr "Kein Artikel gefunden."
#: templates/djangocms_blog/post_list.html:24
msgid "Back"
msgstr "Zurück"
#: templates/djangocms_blog/post_list.html:30
msgid "previous"
msgstr "vorheriger"
#: templates/djangocms_blog/post_list.html:33
msgid "Page"
msgstr "Seite"
#: templates/djangocms_blog/post_list.html:33
msgid "of"
msgstr "von"
#: templates/djangocms_blog/post_list.html:36
msgid "next"
msgstr "nächste"
#: templates/djangocms_blog/includes/blog_item.html:44
msgid "read more"
msgstr "weiterlesen"
#: templates/djangocms_blog/plugins/archive.html:18
#: templates/djangocms_blog/plugins/authors.html:10
#: templates/djangocms_blog/plugins/categories.html:11
#: templates/djangocms_blog/plugins/tags.html:11
#, python-format
msgid "1 article"
msgid_plural "%(articles)s articles"
msgstr[0] "Ein Artikel"
msgstr[1] "%(articles)s Artikel"
#: templates/djangocms_blog/plugins/archive.html:19
#: templates/djangocms_blog/plugins/authors.html:11
#: templates/djangocms_blog/plugins/categories.html:12
#: templates/djangocms_blog/plugins/tags.html:12
msgid "0 articles"
msgstr "0 Artikel"
#~ msgid "blog post"
#~ msgstr "blog post"
#~ msgid "Posts"
#~ msgstr "Posts"
#~ msgid "Entries by"
#~ msgstr "Entries by"
#~ msgid "No entry found."
#~ msgstr "No entry found."

View file

@ -8,20 +8,19 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: djangocms-blog\n" "Project-Id-Version: djangocms-blog\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-06-11 13:11+0200\n" "POT-Creation-Date: 2014-09-01 07:16+0200\n"
"PO-Revision-Date: 2014-04-27 02:30+0000\n" "PO-Revision-Date: 2014-10-12 09:43+0000\n"
"Last-Translator: yakky <i.spalletti@nephila.it>\n" "Last-Translator: yakky <i.spalletti@nephila.it>\n"
"Language-Team: Italian (http://www.transifex.com/projects/p/djangocms-blog/" "Language-Team: Italian (http://www.transifex.com/projects/p/djangocms-blog/language/it/)\n"
"language/it/)\n"
"Language: it\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Language: it\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Lokalize 1.5\n" "X-Generator: Lokalize 1.5\n"
#: cms_app.py:8 cms_plugins.py:32 cms_plugins.py:45 cms_plugins.py:56 #: cms_app.py:8 cms_plugins.py:32 cms_plugins.py:45 cms_plugins.py:56
#: cms_plugins.py:67 cms_toolbar.py:17 #: cms_plugins.py:67 cms_toolbar.py:18
msgid "Blog" msgid "Blog"
msgstr "Blog" msgstr "Blog"
@ -46,15 +45,15 @@ msgstr "Categorie"
msgid "Archive" msgid "Archive"
msgstr "Archivio" msgstr "Archivio"
#: cms_toolbar.py:19 #: cms_toolbar.py:20
msgid "Post list" msgid "Post list"
msgstr "Lista degli articoli" msgstr "Lista degli articoli"
#: cms_toolbar.py:21 #: cms_toolbar.py:22
msgid "Add post" msgid "Add post"
msgstr "Aggiungi articolo" msgstr "Aggiungi articolo"
#: cms_toolbar.py:25 #: cms_toolbar.py:26
msgid "Edit Post" msgid "Edit Post"
msgstr "Modifica articolo" msgstr "Modifica articolo"
@ -63,31 +62,31 @@ msgstr "Modifica articolo"
msgid "Blog articles on %(site_name)s" msgid "Blog articles on %(site_name)s"
msgstr "Articoli del blog su %(site_name)s" msgstr "Articoli del blog su %(site_name)s"
#: models.py:29 #: models.py:28
msgid "parent" msgid "parent"
msgstr "superiore" msgstr "superiore"
#: models.py:31 #: models.py:30
msgid "created at" msgid "created at"
msgstr "creato il" msgstr "creato il"
#: models.py:32 #: models.py:31
msgid "modified at" msgid "modified at"
msgstr "modificato il" msgstr "modificato il"
#: models.py:35 #: models.py:34
msgid "name" msgid "name"
msgstr "nome" msgstr "nome"
#: models.py:36 models.py:95 #: models.py:35 models.py:95
msgid "slug" msgid "slug"
msgstr "slug" msgstr "slug"
#: models.py:43 #: models.py:42
msgid "blog category" msgid "blog category"
msgstr "categoria del blog" msgstr "categoria del blog"
#: models.py:44 #: models.py:43
msgid "blog categories" msgid "blog categories"
msgstr "categorie del blog" msgstr "categorie del blog"
@ -147,31 +146,31 @@ msgstr "Meta keyword dell'articolo"
msgid "Text" msgid "Text"
msgstr "Test" msgstr "Test"
#: models.py:156 #: models.py:158
msgid "blog article" msgid "blog article"
msgstr "articolo del blog" msgstr "articolo del blog"
#: models.py:157 #: models.py:159
msgid "blog articles" msgid "blog articles"
msgstr "articoli del blog" msgstr "articoli del blog"
#: models.py:201 models.py:226 #: models.py:199 models.py:226
msgid "Articles" msgid "Articles"
msgstr "Articoli" msgstr "Articoli"
#: models.py:202 #: models.py:200
msgid "The number of latests articles to be displayed." msgid "The number of latests articles to be displayed."
msgstr "Il numero di articoli da mostrare." msgstr "Il numero di articoli da mostrare."
#: models.py:204 #: models.py:202
msgid "Show only the blog articles tagged with chosen tags." msgid "Show only the blog articles tagged with chosen tags."
msgstr "Mostra solo gli articoli marcati con i tag selezionati." msgstr "Mostra solo gli articoli marcati con i tag selezionati."
#: models.py:206 #: models.py:204
msgid "Show only the blog articles tagged with chosen categories." msgid "Show only the blog articles tagged with chosen categories."
msgstr "Mostra solo gli articoli marcati con i categorie selezionati." msgstr "Mostra solo gli articoli marcati con i categorie selezionati."
#: models.py:223 templates/djangocms_blog/plugins/authors.html:3 #: models.py:222 templates/djangocms_blog/plugins/authors.html:3
msgid "Authors" msgid "Authors"
msgstr "Autori" msgstr "Autori"

Binary file not shown.

View file

@ -0,0 +1,256 @@
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: djangocms-blog\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-09-01 07:16+0200\n"
"PO-Revision-Date: 2014-03-29 15:29+0000\n"
"Last-Translator: Iacopo Spalletti\n"
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/djangocms-blog/language/pt_BR/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: pt_BR\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Lokalize 1.5\n"
#: cms_app.py:8 cms_plugins.py:32 cms_plugins.py:45 cms_plugins.py:56
#: cms_plugins.py:67 cms_toolbar.py:18
msgid "Blog"
msgstr ""
#: cms_plugins.py:20
msgid "Latest Blog Articles"
msgstr ""
#: cms_plugins.py:33
msgid "Author Blog Articles"
msgstr ""
#: cms_plugins.py:46 templates/djangocms_blog/plugins/tags.html:4
msgid "Tags"
msgstr ""
#: cms_plugins.py:57 templates/djangocms_blog/plugins/categories.html:4
msgid "Categories"
msgstr ""
#: cms_plugins.py:68 templates/djangocms_blog/post_list.html:12
#: templates/djangocms_blog/plugins/archive.html:4
msgid "Archive"
msgstr ""
#: cms_toolbar.py:20
msgid "Post list"
msgstr ""
#: cms_toolbar.py:22
msgid "Add post"
msgstr ""
#: cms_toolbar.py:26
msgid "Edit Post"
msgstr ""
#: feeds.py:16
#, python-format
msgid "Blog articles on %(site_name)s"
msgstr ""
#: models.py:28
msgid "parent"
msgstr ""
#: models.py:30
msgid "created at"
msgstr ""
#: models.py:31
msgid "modified at"
msgstr ""
#: models.py:34
msgid "name"
msgstr ""
#: models.py:35 models.py:95
msgid "slug"
msgstr ""
#: models.py:42
msgid "blog category"
msgstr ""
#: models.py:43
msgid "blog categories"
msgstr ""
#: models.py:66
msgid "Author"
msgstr ""
#: models.py:71
msgid "Published Since"
msgstr ""
#: models.py:73
msgid "Published Until"
msgstr ""
#: models.py:75
msgid "Publish"
msgstr ""
#: models.py:76
msgid "category"
msgstr ""
#: models.py:78
msgid "Main image"
msgstr ""
#: models.py:81
msgid "Main image thumbnail"
msgstr ""
#: models.py:85
msgid "Main image full"
msgstr ""
#: models.py:89
msgid "Enable comments on post"
msgstr ""
#: models.py:94
msgid "Title"
msgstr ""
#: models.py:96
msgid "Abstract"
msgstr ""
#: models.py:97
msgid "Post meta description"
msgstr ""
#: models.py:99
msgid "Post meta keywords"
msgstr ""
#: models.py:101
msgid "Text"
msgstr ""
#: models.py:158
msgid "blog article"
msgstr ""
#: models.py:159
msgid "blog articles"
msgstr ""
#: models.py:199 models.py:226
msgid "Articles"
msgstr ""
#: models.py:200
msgid "The number of latests articles to be displayed."
msgstr ""
#: models.py:202
msgid "Show only the blog articles tagged with chosen tags."
msgstr ""
#: models.py:204
msgid "Show only the blog articles tagged with chosen categories."
msgstr ""
#: models.py:222 templates/djangocms_blog/plugins/authors.html:3
msgid "Authors"
msgstr ""
#: models.py:227
msgid "The number of author articles to be displayed."
msgstr ""
#: templates/djangocms_blog/post_detail.html:16
#: templates/djangocms_blog/includes/blog_item.html:10
msgid "by"
msgstr ""
#: templates/djangocms_blog/post_list.html:11
msgid "Articles by"
msgstr ""
#: templates/djangocms_blog/post_list.html:13
msgid "Tag"
msgstr ""
#: templates/djangocms_blog/post_list.html:14
msgid "Category"
msgstr ""
#: templates/djangocms_blog/post_list.html:21
#: templates/djangocms_blog/plugins/archive.html:27
#: templates/djangocms_blog/plugins/authors.html:15
#: templates/djangocms_blog/plugins/categories.html:16
#: templates/djangocms_blog/plugins/latest_entries.html:7
#: templates/djangocms_blog/plugins/tags.html:16
msgid "No article found."
msgstr ""
#: templates/djangocms_blog/post_list.html:24
msgid "Back"
msgstr ""
#: templates/djangocms_blog/post_list.html:30
msgid "previous"
msgstr ""
#: templates/djangocms_blog/post_list.html:33
msgid "Page"
msgstr ""
#: templates/djangocms_blog/post_list.html:33
msgid "of"
msgstr ""
#: templates/djangocms_blog/post_list.html:36
msgid "next"
msgstr ""
#: templates/djangocms_blog/includes/blog_item.html:44
msgid "read more"
msgstr ""
#: templates/djangocms_blog/plugins/archive.html:18
#: templates/djangocms_blog/plugins/authors.html:10
#: templates/djangocms_blog/plugins/categories.html:11
#: templates/djangocms_blog/plugins/tags.html:11
#, python-format
msgid "1 article"
msgid_plural "%(articles)s articles"
msgstr[0] ""
msgstr[1] ""
#: templates/djangocms_blog/plugins/archive.html:19
#: templates/djangocms_blog/plugins/authors.html:11
#: templates/djangocms_blog/plugins/categories.html:12
#: templates/djangocms_blog/plugins/tags.html:12
msgid "0 articles"
msgstr ""
#~ msgid "blog post"
#~ msgstr "blog post"
#~ msgid "Posts"
#~ msgstr "Posts"
#~ msgid "Entries by"
#~ msgstr "Entries by"
#~ msgid "No entry found."
#~ msgstr "No entry found."

View file

@ -7,8 +7,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: djangocms-blog\n" "Project-Id-Version: djangocms-blog\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-04-27 04:29+0200\n" "POT-Creation-Date: 2014-09-01 07:16+0200\n"
"PO-Revision-Date: 2014-04-27 02:29+0000\n" "PO-Revision-Date: 2014-10-12 09:43+0000\n"
"Last-Translator: yakky <i.spalletti@nephila.it>\n" "Last-Translator: yakky <i.spalletti@nephila.it>\n"
"Language-Team: Russian (http://www.transifex.com/projects/p/djangocms-blog/language/ru/)\n" "Language-Team: Russian (http://www.transifex.com/projects/p/djangocms-blog/language/ru/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -19,7 +19,7 @@ msgstr ""
"X-Generator: Lokalize 1.5\n" "X-Generator: Lokalize 1.5\n"
#: cms_app.py:8 cms_plugins.py:32 cms_plugins.py:45 cms_plugins.py:56 #: cms_app.py:8 cms_plugins.py:32 cms_plugins.py:45 cms_plugins.py:56
#: cms_plugins.py:67 cms_toolbar.py:17 #: cms_plugins.py:67 cms_toolbar.py:18
msgid "Blog" msgid "Blog"
msgstr "Блог" msgstr "Блог"
@ -44,15 +44,15 @@ msgstr "Categories"
msgid "Archive" msgid "Archive"
msgstr "Архив" msgstr "Архив"
#: cms_toolbar.py:19 #: cms_toolbar.py:20
msgid "Post list" msgid "Post list"
msgstr "Список статей" msgstr "Список статей"
#: cms_toolbar.py:21 #: cms_toolbar.py:22
msgid "Add post" msgid "Add post"
msgstr "Добавить статью" msgstr "Добавить статью"
#: cms_toolbar.py:25 #: cms_toolbar.py:26
msgid "Edit Post" msgid "Edit Post"
msgstr "" msgstr ""
@ -77,7 +77,7 @@ msgstr "время изменения"
msgid "name" msgid "name"
msgstr "название" msgstr "название"
#: models.py:35 models.py:94 #: models.py:35 models.py:95
msgid "slug" msgid "slug"
msgstr "URL" msgstr "URL"
@ -89,83 +89,83 @@ msgstr "категория блога"
msgid "blog categories" msgid "blog categories"
msgstr "категории блога" msgstr "категории блога"
#: models.py:65 #: models.py:66
msgid "Author" msgid "Author"
msgstr "Автор" msgstr "Автор"
#: models.py:70 #: models.py:71
msgid "Published Since" msgid "Published Since"
msgstr "Опубликована с" msgstr "Опубликована с"
#: models.py:72 #: models.py:73
msgid "Published Until" msgid "Published Until"
msgstr "Опубликована до" msgstr "Опубликована до"
#: models.py:74 #: models.py:75
msgid "Publish" msgid "Publish"
msgstr "Показывать на сайте" msgstr "Показывать на сайте"
#: models.py:75 #: models.py:76
msgid "category" msgid "category"
msgstr "категория" msgstr "категория"
#: models.py:77 #: models.py:78
msgid "Main image" msgid "Main image"
msgstr "Картинка для статьи" msgstr "Картинка для статьи"
#: models.py:80 #: models.py:81
msgid "Main image thumbnail" msgid "Main image thumbnail"
msgstr "Уменьшенная копия" msgstr "Уменьшенная копия"
#: models.py:84 #: models.py:85
msgid "Main image full" msgid "Main image full"
msgstr "Полный размер" msgstr "Полный размер"
#: models.py:88 #: models.py:89
msgid "Enable comments on post" msgid "Enable comments on post"
msgstr "" msgstr ""
#: models.py:93 #: models.py:94
msgid "Title" msgid "Title"
msgstr "Заголовок" msgstr "Заголовок"
#: models.py:95 #: models.py:96
msgid "Abstract" msgid "Abstract"
msgstr "" msgstr ""
#: models.py:96 #: models.py:97
msgid "Post meta description" msgid "Post meta description"
msgstr "" msgstr ""
#: models.py:98 #: models.py:99
msgid "Post meta keywords" msgid "Post meta keywords"
msgstr "" msgstr ""
#: models.py:100 #: models.py:101
msgid "Text" msgid "Text"
msgstr "" msgstr ""
#: models.py:155 #: models.py:158
msgid "blog article" msgid "blog article"
msgstr "статья блога" msgstr "статья блога"
#: models.py:156 #: models.py:159
msgid "blog articles" msgid "blog articles"
msgstr "статьи блога" msgstr "статьи блога"
#: models.py:200 models.py:225 #: models.py:199 models.py:226
msgid "Articles" msgid "Articles"
msgstr "Статьи" msgstr "Статьи"
#: models.py:201 #: models.py:200
msgid "The number of latests articles to be displayed." msgid "The number of latests articles to be displayed."
msgstr "Количество показываемых последних статей." msgstr "Количество показываемых последних статей."
#: models.py:203 #: models.py:202
msgid "Show only the blog articles tagged with chosen tags." msgid "Show only the blog articles tagged with chosen tags."
msgstr "Показывать только статьи с выбранными тэгами." msgstr "Показывать только статьи с выбранными тэгами."
#: models.py:205 #: models.py:204
msgid "Show only the blog articles tagged with chosen categories." msgid "Show only the blog articles tagged with chosen categories."
msgstr "Показывать только статьи из выбранныех категорий." msgstr "Показывать только статьи из выбранныех категорий."
@ -173,7 +173,7 @@ msgstr "Показывать только статьи из выбранныех
msgid "Authors" msgid "Authors"
msgstr "Авторы" msgstr "Авторы"
#: models.py:226 #: models.py:227
msgid "The number of author articles to be displayed." msgid "The number of author articles to be displayed."
msgstr "Количество статей автора, которые будут показаны." msgstr "Количество статей автора, которые будут показаны."

View file

@ -1,4 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import django
from django.contrib.sites.models import Site
from django.db.models import Q
try: try:
from collections import Counter from collections import Counter
except ImportError: except ImportError:
@ -6,7 +10,7 @@ except ImportError:
from django.db import models from django.db import models
from django.utils.timezone import now from django.utils.timezone import now
from parler.managers import TranslationManager from parler.managers import TranslationManager, TranslatableQuerySet
class TaggedFilterItem(object): class TaggedFilterItem(object):
@ -68,29 +72,24 @@ class TaggedFilterItem(object):
return sorted(tags, key=lambda x: -x.count) return sorted(tags, key=lambda x: -x.count)
class GenericDateTaggedManager(TaggedFilterItem, TranslationManager): class GenericDateQuerySet(TranslatableQuerySet):
use_for_related_fields = True
start_date_field = 'date_published' start_date_field = 'date_published'
end_date_field = 'date_published_end' end_date_field = 'date_published_end'
publish_field = 'publish' publish_field = 'publish'
def get_queryset(self, *args, **kwargs): def on_site(self):
try: return self.filter(Q(sites__isnull=True) | Q(sites=Site.objects.get_current().pk))
return super(GenericDateTaggedManager, self).get_queryset(*args, **kwargs)
except AttributeError:
return super(GenericDateTaggedManager, self).get_query_set(*args, **kwargs)
def published(self, queryset=None): def published(self):
queryset = self.published_future(queryset) queryset = self.published_future()
if self.start_date_field: if self.start_date_field:
return queryset.filter( return queryset.filter(
**{'%s__lte' % self.start_date_field: now()}) **{'%s__lte' % self.start_date_field: now()})
else: else:
return queryset return queryset
def published_future(self, queryset=None): def published_future(self):
if queryset is None: queryset = self.on_site()
queryset = self.get_queryset().all()
if self.end_date_field: if self.end_date_field:
qfilter = ( qfilter = (
models.Q(**{'%s__gte' % self.end_date_field: now()}) models.Q(**{'%s__gte' % self.end_date_field: now()})
@ -99,9 +98,8 @@ class GenericDateTaggedManager(TaggedFilterItem, TranslationManager):
queryset = queryset.filter(qfilter) queryset = queryset.filter(qfilter)
return queryset.filter(**{self.publish_field: True}) return queryset.filter(**{self.publish_field: True})
def archived(self, queryset=None): def archived(self):
if queryset is None: queryset = self.on_site()
queryset = self.get_queryset().all()
if self.end_date_field: if self.end_date_field:
qfilter = ( qfilter = (
models.Q(**{'%s__lte' % self.end_date_field: now()}) models.Q(**{'%s__lte' % self.end_date_field: now()})
@ -110,13 +108,40 @@ class GenericDateTaggedManager(TaggedFilterItem, TranslationManager):
queryset = queryset.filter(qfilter) queryset = queryset.filter(qfilter)
return queryset.filter(**{self.publish_field: True}) return queryset.filter(**{self.publish_field: True})
def available(self, queryset=None): def available(self):
if queryset is None: return self.on_site().filter(**{self.publish_field: True})
queryset = self.get_queryset().all()
return queryset.filter(**{self.publish_field: True})
def filter_by_language(self, language): def filter_by_language(self, language):
return self.get_queryset().active_translations(language_code=language) return self.active_translations(language_code=language).on_site()
class GenericDateTaggedManager(TaggedFilterItem, TranslationManager):
use_for_related_fields = True
queryset_class = GenericDateQuerySet
def get_queryset(self, *args, **kwargs):
try:
return super(GenericDateTaggedManager, self).get_queryset(*args, **kwargs)
except AttributeError: # pragma: no cover
return super(GenericDateTaggedManager, self).get_query_set(*args, **kwargs)
if django.VERSION < (1, 8):
get_query_set = get_queryset
def published(self):
return self.get_queryset().published()
def available(self):
return self.get_queryset().available()
def archived(self):
return self.get_queryset().archived()
def published_future(self):
return self.get_queryset().published_future()
def filter_by_language(self, language):
return self.get_queryset().filter_by_language(language)
def get_months(self, queryset=None): def get_months(self, queryset=None):
""" """
@ -124,7 +149,8 @@ class GenericDateTaggedManager(TaggedFilterItem, TranslationManager):
""" """
if queryset is None: if queryset is None:
queryset = self.get_queryset() queryset = self.get_queryset()
dates = queryset.values_list(self.start_date_field, flat=True) queryset = queryset.on_site()
dates = queryset.values_list(queryset.start_date_field, flat=True)
dates = [(x.year, x.month) for x in dates] dates = [(x.year, x.month) for x in dates]
date_counter = Counter(dates) date_counter = Counter(dates)
dates = set(dates) dates = set(dates)

View file

@ -0,0 +1,209 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding M2M table for field sites on 'Post'
m2m_table_name = db.shorten_name(u'djangocms_blog_post_sites')
db.create_table(m2m_table_name, (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('post', models.ForeignKey(orm[u'djangocms_blog.post'], null=False)),
('site', models.ForeignKey(orm[u'sites.site'], null=False))
))
db.create_unique(m2m_table_name, ['post_id', 'site_id'])
def backwards(self, orm):
# Removing M2M table for field sites on 'Post'
db.delete_table(db.shorten_name(u'djangocms_blog_post_sites'))
models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'cms.cmsplugin': {
'Meta': {'object_name': 'CMSPlugin'},
'changed_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'creation_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}),
'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cms.CMSPlugin']", 'null': 'True', 'blank': 'True'}),
'placeholder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cms.Placeholder']", 'null': 'True'}),
'plugin_type': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}),
'position': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True', 'blank': 'True'}),
'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
},
'cms.placeholder': {
'Meta': {'object_name': 'Placeholder'},
'default_width': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'slot': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
},
u'cmsplugin_filer_image.thumbnailoption': {
'Meta': {'ordering': "('width', 'height')", 'object_name': 'ThumbnailOption'},
'crop': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'height': ('django.db.models.fields.IntegerField', [], {}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'upscale': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'width': ('django.db.models.fields.IntegerField', [], {})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'djangocms_blog.authorentriesplugin': {
'Meta': {'object_name': 'AuthorEntriesPlugin', '_ormbases': ['cms.CMSPlugin']},
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'symmetrical': 'False'}),
u'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['cms.CMSPlugin']", 'unique': 'True', 'primary_key': 'True'}),
'latest_posts': ('django.db.models.fields.IntegerField', [], {'default': '5'})
},
u'djangocms_blog.blogcategory': {
'Meta': {'object_name': 'BlogCategory'},
'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['djangocms_blog.BlogCategory']", 'null': 'True', 'blank': 'True'})
},
u'djangocms_blog.blogcategorytranslation': {
'Meta': {'unique_together': "[('language_code', 'slug'), (u'language_code', u'master')]", 'object_name': 'BlogCategoryTranslation', 'db_table': "u'djangocms_blog_blogcategory_translation'"},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language_code': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}),
u'master': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'translations'", 'null': 'True', 'to': u"orm['djangocms_blog.BlogCategory']"}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'blank': 'True'})
},
u'djangocms_blog.latestpostsplugin': {
'Meta': {'object_name': 'LatestPostsPlugin', '_ormbases': ['cms.CMSPlugin']},
'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['djangocms_blog.BlogCategory']", 'symmetrical': 'False', 'blank': 'True'}),
u'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['cms.CMSPlugin']", 'unique': 'True', 'primary_key': 'True'}),
'latest_posts': ('django.db.models.fields.IntegerField', [], {'default': '5'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['taggit.Tag']", 'symmetrical': 'False', 'blank': 'True'})
},
u'djangocms_blog.post': {
'Meta': {'ordering': "('-date_published', '-date_created')", 'object_name': 'Post'},
'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'djangocms_blog_post_author'", 'null': 'True', 'to': u"orm['auth.User']"}),
'categories': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'blog_posts'", 'symmetrical': 'False', 'to': u"orm['djangocms_blog.BlogCategory']"}),
'content': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cms.Placeholder']", 'null': 'True'}),
'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'date_published': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'date_published_end': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'enable_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'main_image': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'djangocms_blog_post_image'", 'null': 'True', 'to': "orm['filer.Image']"}),
'main_image_full': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'djangocms_blog_post_full'", 'null': 'True', 'to': u"orm['cmsplugin_filer_image.ThumbnailOption']"}),
'main_image_thumbnail': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'djangocms_blog_post_thumbnail'", 'null': 'True', 'to': u"orm['cmsplugin_filer_image.ThumbnailOption']"}),
'publish': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'sites': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['sites.Site']", 'null': 'True', 'blank': 'True'})
},
u'djangocms_blog.posttranslation': {
'Meta': {'unique_together': "[('language_code', 'slug'), (u'language_code', u'master')]", 'object_name': 'PostTranslation', 'db_table': "u'djangocms_blog_post_translation'"},
'abstract': ('djangocms_text_ckeditor.fields.HTMLField', [], {}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language_code': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}),
u'master': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'translations'", 'null': 'True', 'to': u"orm['djangocms_blog.Post']"}),
'meta_description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
'meta_keywords': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
'meta_title': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255', 'blank': 'True'}),
'post_text': ('djangocms_text_ckeditor.fields.HTMLField', [], {'default': "''", 'blank': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'blank': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'})
},
u'filer.file': {
'Meta': {'object_name': 'File'},
'_file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'folder': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'all_files'", 'null': 'True', 'to': u"orm['filer.Folder']"}),
'has_all_mandatory_data': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
'original_filename': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'owned_files'", 'null': 'True', 'to': u"orm['auth.User']"}),
'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'polymorphic_filer.file_set'", 'null': 'True', 'to': u"orm['contenttypes.ContentType']"}),
'sha1': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '40', 'blank': 'True'}),
'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
},
u'filer.folder': {
'Meta': {'ordering': "(u'name',)", 'unique_together': "((u'parent', u'name'),)", 'object_name': 'Folder'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
u'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
u'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'filer_owned_folders'", 'null': 'True', 'to': u"orm['auth.User']"}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'children'", 'null': 'True', 'to': u"orm['filer.Folder']"}),
u'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
u'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
},
'filer.image': {
'Meta': {'object_name': 'Image', '_ormbases': [u'filer.File']},
'_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'author': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'date_taken': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'default_alt_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'default_caption': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
u'file_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['filer.File']", 'unique': 'True', 'primary_key': 'True'}),
'must_always_publish_author_credit': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'must_always_publish_copyright': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'subject_location': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '64', 'null': 'True', 'blank': 'True'})
},
u'sites.site': {
'Meta': {'ordering': "(u'domain',)", 'object_name': 'Site', 'db_table': "u'django_site'"},
'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'taggit.tag': {
'Meta': {'object_name': 'Tag'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'})
}
}
complete_apps = ['djangocms_blog']

View file

@ -0,0 +1,135 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import taggit_autosuggest.managers
import filer.fields.image
import meta_mixin.models
import djangocms_text_ckeditor.fields
import cms.models.fields
import django.utils.timezone
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('cms', '0003_auto_20140926_2347'),
('taggit', '__first__'),
('filer', '0001_initial'),
('cmsplugin_filer_image', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='AuthorEntriesPlugin',
fields=[
('cmsplugin_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='cms.CMSPlugin')),
('latest_posts', models.IntegerField(default=5, help_text='The number of author articles to be displayed.', verbose_name='Articles')),
('authors', models.ManyToManyField(to=settings.AUTH_USER_MODEL, verbose_name='Authors')),
],
options={
'abstract': False,
},
bases=('cms.cmsplugin',),
),
migrations.CreateModel(
name='BlogCategory',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('date_created', models.DateTimeField(auto_now_add=True, verbose_name='created at')),
('date_modified', models.DateTimeField(auto_now=True, verbose_name='modified at')),
('parent', models.ForeignKey(verbose_name='parent', blank=True, to='djangocms_blog.BlogCategory', null=True)),
],
options={
'verbose_name': 'blog category',
'verbose_name_plural': 'blog categories',
},
bases=(models.Model,),
),
migrations.CreateModel(
name='BlogCategoryTranslation',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('language_code', models.CharField(db_index=True, max_length=15, verbose_name='Language', choices=[(b'lt', b'Lithuanian'), (b'en', b'English')])),
('name', models.CharField(max_length=255, verbose_name='name')),
('slug', models.SlugField(verbose_name='slug', blank=True)),
('master', models.ForeignKey(related_name='translations', editable=False, to='djangocms_blog.BlogCategory', null=True)),
],
options={
'db_table': 'djangocms_blog_blogcategory_translation',
'verbose_name': 'blog category Translation',
'default_permissions': (),
},
bases=(models.Model,),
),
migrations.CreateModel(
name='LatestPostsPlugin',
fields=[
('cmsplugin_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='cms.CMSPlugin')),
('latest_posts', models.IntegerField(default=5, help_text='The number of latests articles to be displayed.', verbose_name='Articles')),
('categories', models.ManyToManyField(help_text='Show only the blog articles tagged with chosen categories.', to='djangocms_blog.BlogCategory', blank=True)),
('tags', models.ManyToManyField(help_text='Show only the blog articles tagged with chosen tags.', to='taggit.Tag', blank=True)),
],
options={
'abstract': False,
},
bases=('cms.cmsplugin',),
),
migrations.CreateModel(
name='Post',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('date_created', models.DateTimeField(auto_now_add=True)),
('date_modified', models.DateTimeField(auto_now=True)),
('date_published', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Published Since')),
('date_published_end', models.DateTimeField(null=True, verbose_name='Published Until', blank=True)),
('publish', models.BooleanField(default=False, verbose_name='Publish')),
('enable_comments', models.BooleanField(default=True, verbose_name='Enable comments on post')),
('author', models.ForeignKey(related_name='djangocms_blog_post_author', verbose_name='Author', blank=True, to=settings.AUTH_USER_MODEL, null=True)),
('categories', models.ManyToManyField(related_name='blog_posts', verbose_name='category', to='djangocms_blog.BlogCategory')),
('content', cms.models.fields.PlaceholderField(slotname=b'post_content', editable=False, to='cms.Placeholder', null=True)),
('main_image', filer.fields.image.FilerImageField(related_name='djangocms_blog_post_image', verbose_name='Main image', blank=True, to='filer.Image', null=True)),
('main_image_full', models.ForeignKey(related_name='djangocms_blog_post_full', verbose_name='Main image full', blank=True, to='cmsplugin_filer_image.ThumbnailOption', null=True)),
('main_image_thumbnail', models.ForeignKey(related_name='djangocms_blog_post_thumbnail', verbose_name='Main image thumbnail', blank=True, to='cmsplugin_filer_image.ThumbnailOption', null=True)),
('tags', taggit_autosuggest.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags')),
],
options={
'ordering': ('-date_published', '-date_created'),
'get_latest_by': 'date_published',
'verbose_name': 'blog article',
'verbose_name_plural': 'blog articles',
},
bases=(meta_mixin.models.ModelMeta, models.Model),
),
migrations.CreateModel(
name='PostTranslation',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('language_code', models.CharField(db_index=True, max_length=15, verbose_name='Language', choices=[(b'lt', b'Lithuanian'), (b'en', b'English')])),
('title', models.CharField(max_length=255, verbose_name='Title')),
('slug', models.SlugField(verbose_name='slug', blank=True)),
('abstract', djangocms_text_ckeditor.fields.HTMLField(verbose_name='Abstract')),
('meta_description', models.TextField(default=b'', verbose_name='Post meta description', blank=True)),
('meta_keywords', models.TextField(default=b'', verbose_name='Post meta keywords', blank=True)),
('meta_title', models.CharField(default=b'', help_text='used in title tag and social sharing', max_length=255, verbose_name='Post meta title', blank=True)),
('post_text', djangocms_text_ckeditor.fields.HTMLField(default=b'', verbose_name='Text', blank=True)),
('master', models.ForeignKey(related_name='translations', editable=False, to='djangocms_blog.Post', null=True)),
],
options={
'db_table': 'djangocms_blog_post_translation',
'verbose_name': 'blog article Translation',
'default_permissions': (),
},
bases=(models.Model,),
),
migrations.AlterUniqueTogether(
name='posttranslation',
unique_together=set([('language_code', 'master'), ('language_code', 'slug')]),
),
migrations.AlterUniqueTogether(
name='blogcategorytranslation',
unique_together=set([('language_code', 'master'), ('language_code', 'slug')]),
),
]

View file

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('sites', '0001_initial'),
('djangocms_blog', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='post',
name='sites',
field=models.ManyToManyField(help_text='Select sites in which to show the post. If none is set it will bevisible in all the configured sites.', to='sites.Site', null=True, verbose_name='Site(s', blank=True),
preserve_default=True,
),
]

View file

@ -2,25 +2,28 @@
from cms.models import PlaceholderField, CMSPlugin from cms.models import PlaceholderField, CMSPlugin
from cmsplugin_filer_image.models import ThumbnailOption from cmsplugin_filer_image.models import ThumbnailOption
from django.conf import settings as dj_settings from django.conf import settings as dj_settings
from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
from django.utils.encoding import force_text from django.utils.encoding import force_text, python_2_unicode_compatible
from django.utils.html import strip_tags, escape
from django.utils.text import slugify from django.utils.text import slugify
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _, get_language
from djangocms_text_ckeditor.fields import HTMLField from djangocms_text_ckeditor.fields import HTMLField
from filer.fields.image import FilerImageField from filer.fields.image import FilerImageField
from meta_mixin.models import ModelMeta
from parler.models import TranslatableModel, TranslatedFields from parler.models import TranslatableModel, TranslatedFields
from parler.managers import TranslationManager from parler.managers import TranslationManager
from taggit_autosuggest.managers import TaggableManager from taggit_autosuggest.managers import TaggableManager
from . import settings from .settings import get_setting
from meta_mixin.models import ModelMeta
from .managers import GenericDateTaggedManager from .managers import GenericDateTaggedManager
BLOG_CURRENT_POST_IDENTIFIER = 'djangocms_post_current' BLOG_CURRENT_POST_IDENTIFIER = 'djangocms_post_current'
@python_2_unicode_compatible
class BlogCategory(TranslatableModel): class BlogCategory(TranslatableModel):
""" """
Blog category Blog category
@ -46,7 +49,7 @@ class BlogCategory(TranslatableModel):
def count(self): def count(self):
return self.blog_posts.filter(publish=True).count() return self.blog_posts.filter(publish=True).count()
def __unicode__(self): def __str__(self):
return self.safe_translation_getter('name') return self.safe_translation_getter('name')
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
@ -58,6 +61,7 @@ class BlogCategory(TranslatableModel):
self.save_translations() self.save_translations()
@python_2_unicode_compatible
class Post(ModelMeta, TranslatableModel): class Post(ModelMeta, TranslatableModel):
""" """
Blog post Blog post
@ -87,8 +91,12 @@ class Post(ModelMeta, TranslatableModel):
blank=True, null=True) blank=True, null=True)
enable_comments = models.BooleanField( enable_comments = models.BooleanField(
verbose_name=_(u'Enable comments on post'), verbose_name=_(u'Enable comments on post'),
default=settings.BLOG_ENABLE_COMMENTS default=get_setting('ENABLE_COMMENTS')
) )
sites = models.ManyToManyField(Site, verbose_name=_(u'Site(s'), blank=True, null=True,
help_text=_(u'Select sites in which to show the post. If none is set it will be'
u'visible in all the configured sites.')
)
translations = TranslatedFields( translations = TranslatedFields(
title=models.CharField(_('Title'), max_length=255), title=models.CharField(_('Title'), max_length=255),
@ -119,17 +127,17 @@ class Post(ModelMeta, TranslatableModel):
'keywords': 'get_keywords', 'keywords': 'get_keywords',
'locale': None, 'locale': None,
'image': 'get_image_full_url', 'image': 'get_image_full_url',
'object_type': settings.BLOG_TYPE, 'object_type': get_setting('TYPE'),
'og_type': settings.BLOG_FB_TYPE, 'og_type': get_setting('FB_TYPE'),
'og_app_id': settings.BLOG_FB_APPID, 'og_app_id': get_setting('FB_APPID'),
'og_profile_id': settings.BLOG_FB_PROFILE_ID, 'og_profile_id': get_setting('FB_PROFILE_ID'),
'og_publisher': settings.BLOG_FB_PUBLISHER, 'og_publisher': get_setting('FB_PUBLISHER'),
'og_author_url': settings.BLOG_FB_AUTHOR_URL, 'og_author_url': get_setting('FB_AUTHOR_URL'),
'twitter_type': settings.BLOG_TWITTER_TYPE, 'twitter_type': get_setting('TWITTER_TYPE'),
'twitter_site': settings.BLOG_TWITTER_SITE, 'twitter_site': get_setting('TWITTER_SITE'),
'twitter_author': settings.BLOG_TWITTER_AUTHOR, 'twitter_author': get_setting('TWITTER_AUTHOR'),
'gplus_type': settings.BLOG_GPLUS_TYPE, 'gplus_type': get_setting('GPLUS_TYPE'),
'gplus_author': settings.BLOG_GPLUS_AUTHOR, 'gplus_author': get_setting('GPLUS_AUTHOR'),
'published_time': 'date_published', 'published_time': 'date_published',
'modified_time': 'date_modified', 'modified_time': 'date_modified',
'expiration_time': 'date_published_end', 'expiration_time': 'date_published_end',
@ -150,7 +158,7 @@ class Post(ModelMeta, TranslatableModel):
description = self.safe_translation_getter('meta_description', any_language=True) description = self.safe_translation_getter('meta_description', any_language=True)
if not description: if not description:
description = self.safe_translation_getter('abstract', any_language=True) description = self.safe_translation_getter('abstract', any_language=True)
return description.strip() return escape(strip_tags(description)).strip()
def get_image_full_url(self): def get_image_full_url(self):
if self.main_image: if self.main_image:
@ -170,50 +178,53 @@ class Post(ModelMeta, TranslatableModel):
ordering = ('-date_published', '-date_created') ordering = ('-date_published', '-date_created')
get_latest_by = 'date_published' get_latest_by = 'date_published'
def __unicode__(self): def __str__(self):
return self.safe_translation_getter('title') return self.safe_translation_getter('title')
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
super(Post, self).save(*args, **kwargs) super(Post, self).save(*args, **kwargs)
main_lang = self.get_current_language()
for lang in self.get_available_languages(): for lang in self.get_available_languages():
self.set_current_language(lang) self.set_current_language(lang)
if not self.slug and self.title: if not self.slug and self.title:
self.slug = slugify(self.title) self.slug = slugify(self.title)
self.set_current_language(main_lang)
self.save_translations() self.save_translations()
def get_absolute_url(self): def get_absolute_url(self):
kwargs = {'year': self.date_published.year, kwargs = {'year': self.date_published.year,
'month': self.date_published.month, 'month': '%02d' % self.date_published.month,
'day': self.date_published.day, 'day': '%02d' % self.date_published.day,
'slug': self.safe_translation_getter('slug', any_language=True)} 'slug': self.safe_translation_getter('slug', language_code=get_language())}
return reverse('djangocms_blog:post-detail', kwargs=kwargs) return reverse('djangocms_blog:post-detail', kwargs=kwargs)
def thumbnail_options(self): def thumbnail_options(self):
if self.main_image_thumbnail_id: if self.main_image_thumbnail_id:
return self.main_image_thumbnail.as_dict return self.main_image_thumbnail.as_dict
else: else:
return settings.BLOG_IMAGE_THUMBNAIL_SIZE return get_setting('IMAGE_THUMBNAIL_SIZE')
def full_image_options(self): def full_image_options(self):
if self.main_image_full_id: if self.main_image_full_id:
return self.main_image_full.as_dict return self.main_image_full.as_dict
else: else:
return settings.BLOG_IMAGE_FULL_SIZE return get_setting('IMAGE_FULL_SIZE')
def get_full_url(self): def get_full_url(self):
return self.make_full_url(self.get_absolute_url()) return self.make_full_url(self.get_absolute_url())
@python_2_unicode_compatible
class LatestPostsPlugin(CMSPlugin): class LatestPostsPlugin(CMSPlugin):
latest_posts = models.IntegerField(_(u'Articles'), default=settings.BLOG_LATEST_POSTS, latest_posts = models.IntegerField(_(u'Articles'), default=get_setting('LATEST_POSTS'),
help_text=_('The number of latests articles to be displayed.')) help_text=_('The number of latests articles to be displayed.'))
tags = models.ManyToManyField('taggit.Tag', blank=True, tags = models.ManyToManyField('taggit.Tag', blank=True,
help_text=_('Show only the blog articles tagged with chosen tags.')) help_text=_('Show only the blog articles tagged with chosen tags.'))
categories = models.ManyToManyField('BlogCategory', blank=True, categories = models.ManyToManyField('BlogCategory', blank=True,
help_text=_('Show only the blog articles tagged with chosen categories.')) help_text=_('Show only the blog articles tagged with chosen categories.'))
def __unicode__(self): def __str__(self):
return u'%s latest articles by tag' % self.latest_posts return u'%s latest articles by tag' % self.latest_posts
def copy_relations(self, oldinstance): def copy_relations(self, oldinstance):
@ -227,17 +238,18 @@ class LatestPostsPlugin(CMSPlugin):
return posts[:self.latest_posts] return posts[:self.latest_posts]
@python_2_unicode_compatible
class AuthorEntriesPlugin(CMSPlugin): class AuthorEntriesPlugin(CMSPlugin):
authors = models.ManyToManyField( authors = models.ManyToManyField(
dj_settings.AUTH_USER_MODEL, verbose_name=_('Authors'), dj_settings.AUTH_USER_MODEL, verbose_name=_('Authors'),
limit_choices_to={'djangocms_blog_post_author__publish': True} limit_choices_to={'djangocms_blog_post_author__publish': True}
) )
latest_posts = models.IntegerField( latest_posts = models.IntegerField(
_(u'Articles'), default=settings.BLOG_LATEST_POSTS, _(u'Articles'), default=get_setting('LATEST_POSTS'),
help_text=_('The number of author articles to be displayed.') help_text=_('The number of author articles to be displayed.')
) )
def __unicode__(self): def __str__(self):
return u'%s latest articles by author' % self.latest_posts return u'%s latest articles by author' % self.latest_posts
def copy_relations(self, oldinstance): def copy_relations(self, oldinstance):

View file

@ -1,35 +1,54 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.conf import settings
from meta_mixin import settings as meta_settings
BLOG_IMAGE_THUMBNAIL_SIZE = getattr(settings, 'BLOG_IMAGE_THUMBNAIL_SIZE', {
'size': '120x120',
'crop': True,
'upscale': False
})
BLOG_IMAGE_FULL_SIZE = getattr(settings, 'BLOG_IMAGE_FULL_SIZE', { def get_setting(name):
'size': '640x120', from django.conf import settings
'crop': True, from meta_mixin import settings as meta_settings
'upscale': False
})
BLOG_TAGCLOUD_MIN = getattr(settings, 'BLOG_TAGCLOUD_MIN', 1) default = {
BLOG_TAGCLOUD_MAX = getattr(settings, 'BLOG_TAGCLOUD_MAX', 10) 'BLOG_IMAGE_THUMBNAIL_SIZE': getattr(settings, 'BLOG_IMAGE_THUMBNAIL_SIZE', {
BLOG_PAGINATION = getattr(settings, 'BLOG_PAGINATION', 10) 'size': '120x120',
BLOG_LATEST_POSTS = getattr(settings, 'BLOG_LATEST_POSTS', 5) 'crop': True,
BLOG_POSTS_LIST_TRUNCWORDS_COUNT = getattr(settings, 'BLOG_POSTS_LIST_TRUNCWORDS_COUNT', 100) 'upscale': False
BLOG_TYPE = getattr(settings, 'BLOG_TYPE', 'Article') }),
BLOG_FB_TYPE = getattr(settings, 'BLOG_FB_TYPE', 'Article')
BLOG_FB_APPID = getattr(settings, 'BLOG_FB_APPID', meta_settings.FB_APPID) 'BLOG_IMAGE_FULL_SIZE': getattr(settings, 'BLOG_IMAGE_FULL_SIZE', {
BLOG_FB_PROFILE_ID = getattr(settings, 'BLOG_FB_PROFILE_ID', meta_settings.FB_PROFILE_ID) 'size': '640x120',
BLOG_FB_PUBLISHER = getattr(settings, 'BLOG_FB_PUBLISHER', meta_settings.FB_PUBLISHER) 'crop': True,
BLOG_FB_AUTHOR_URL = getattr(settings, 'BLOG_FB_AUTHOR_URL', 'get_author_url') 'upscale': False
BLOG_FB_AUTHOR = getattr(settings, 'BLOG_FB_AUTHOR', 'get_author_name') }),
BLOG_TWITTER_TYPE = getattr(settings, 'BLOG_TWITTER_TYPE', 'Summary')
BLOG_TWITTER_SITE = getattr(settings, 'BLOG_TWITTER_SITE', meta_settings.TWITTER_SITE) 'BLOG_TAGCLOUD_MIN': getattr(settings, 'BLOG_TAGCLOUD_MIN', 1),
BLOG_TWITTER_AUTHOR = getattr(settings, 'BLOG_TWITTER_AUTHOR', 'get_author_twitter') 'BLOG_TAGCLOUD_MAX': getattr(settings, 'BLOG_TAGCLOUD_MAX', 10),
BLOG_GPLUS_TYPE = getattr(settings, 'BLOG_GPLUS_SCOPE_CATEGORY', 'Blog') 'BLOG_PAGINATION': getattr(settings, 'BLOG_PAGINATION', 10),
BLOG_GPLUS_AUTHOR = getattr(settings, 'BLOG_GPLUS_AUTHOR', 'get_author_gplus') 'BLOG_LATEST_POSTS': getattr(settings, 'BLOG_LATEST_POSTS', 5),
BLOG_ENABLE_COMMENTS = getattr(settings, 'BLOG_ENABLE_COMMENTS', True) 'BLOG_POSTS_LIST_TRUNCWORDS_COUNT': getattr(settings,
BLOG_USE_PLACEHOLDER = getattr(settings, 'BLOG_USE_PLACEHOLDER', True) 'BLOG_POSTS_LIST_TRUNCWORDS_COUNT',
100),
'BLOG_TYPE': getattr(settings, 'BLOG_TYPE', 'Article'),
'BLOG_FB_TYPE': getattr(settings, 'BLOG_FB_TYPE', 'Article'),
'BLOG_FB_APPID': getattr(settings, 'BLOG_FB_APPID',
meta_settings.FB_APPID),
'BLOG_FB_PROFILE_ID': getattr(settings, 'BLOG_FB_PROFILE_ID',
meta_settings.FB_PROFILE_ID),
'BLOG_FB_PUBLISHER': getattr(settings, 'BLOG_FB_PUBLISHER',
meta_settings.FB_PUBLISHER),
'BLOG_FB_AUTHOR_URL': getattr(settings, 'BLOG_FB_AUTHOR_URL',
'get_author_url'),
'BLOG_FB_AUTHOR': getattr(settings, 'BLOG_FB_AUTHOR',
'get_author_name'),
'BLOG_TWITTER_TYPE': getattr(settings, 'BLOG_TWITTER_TYPE', 'Summary'),
'BLOG_TWITTER_SITE': getattr(settings, 'BLOG_TWITTER_SITE',
meta_settings.TWITTER_SITE),
'BLOG_TWITTER_AUTHOR': getattr(settings, 'BLOG_TWITTER_AUTHOR',
'get_author_twitter'),
'BLOG_GPLUS_TYPE': getattr(settings, 'BLOG_GPLUS_SCOPE_CATEGORY',
'Blog'),
'BLOG_GPLUS_AUTHOR': getattr(settings, 'BLOG_GPLUS_AUTHOR',
'get_author_gplus'),
'BLOG_ENABLE_COMMENTS': getattr(settings, 'BLOG_ENABLE_COMMENTS', True),
'BLOG_USE_PLACEHOLDER': getattr(settings, 'BLOG_USE_PLACEHOLDER', True),
'BLOG_MULTISITE': getattr(settings, 'BLOG_MULTISITE', True),
'BLOG_AUTHOR_DEFAULT': getattr(settings, 'BLOG_AUTHOR_DEFAULT', True),
}
return default['BLOG_%s' % name]

View file

@ -6,9 +6,11 @@
<h3><a href="{{ post.get_absolute_url }}">{{ post.title }}</a></h3> <h3><a href="{{ post.get_absolute_url }}">{{ post.title }}</a></h3>
{% block blog_meta %} {% block blog_meta %}
<ul class="post-detail"> <ul class="post-detail">
{% if post.author %}
<li> <li>
{% trans "by" %} <a href="{% url 'djangocms_blog:posts-author' post.author.get_username %}">{{ post.author.get_full_name }}</a> {% trans "by" %} <a href="{% url 'djangocms_blog:posts-author' post.author.get_username %}">{{ post.author.get_full_name }}</a>
</li> </li>
{% endif %}
<li> <li>
{{ post.date_published|date:"M d, Y" }} {{ post.date_published|date:"M d, Y" }}
</li> </li>

View file

@ -13,9 +13,11 @@
<h2>{% render_model post "title" %}</h2> <h2>{% render_model post "title" %}</h2>
{% block blog_meta %} {% block blog_meta %}
<ul class="post-detail"> <ul class="post-detail">
{% if post.author %}
<li> <li>
{% trans "by" %} <a href="{% url 'djangocms_blog:posts-author' post.author.get_username %}">{{ post.author.get_full_name }}</a> {% trans "by" %} <a href="{% url 'djangocms_blog:posts-author' post.author.get_username %}">{{ post.author.get_full_name }}</a>
</li> </li>
{% endif %}
<li> <li>
{{ post.date_published|date:"M d, Y" }} {{ post.date_published|date:"M d, Y" }}
</li> </li>

View file

@ -8,8 +8,7 @@ from django.views.generic import ListView, DetailView
from parler.views import ViewUrlMixin, TranslatableSlugMixin from parler.views import ViewUrlMixin, TranslatableSlugMixin
from .models import Post, BlogCategory, BLOG_CURRENT_POST_IDENTIFIER from .models import Post, BlogCategory, BLOG_CURRENT_POST_IDENTIFIER
from .settings import (BLOG_PAGINATION, BLOG_POSTS_LIST_TRUNCWORDS_COUNT, from .settings import get_setting
BLOG_USE_PLACEHOLDER)
User = get_user_model() User = get_user_model()
@ -18,10 +17,10 @@ class BaseBlogView(ViewUrlMixin):
def get_queryset(self): def get_queryset(self):
language = get_language() language = get_language()
manager = self.model._default_manager.active_translations(language_code=language) queryset = self.model._default_manager.language(language_code=language)
if not self.request.user.is_staff: if not self.request.toolbar or not self.request.toolbar.edit_mode:
manager = manager.filter(publish=True) queryset = queryset.published()
return manager return queryset.on_site()
def render_to_response(self, context, **response_kwargs): def render_to_response(self, context, **response_kwargs):
response_kwargs['current_app'] = resolve(self.request.path).namespace response_kwargs['current_app'] = resolve(self.request.path).namespace
@ -32,12 +31,12 @@ class PostListView(BaseBlogView, ListView):
model = Post model = Post
context_object_name = 'post_list' context_object_name = 'post_list'
template_name = 'djangocms_blog/post_list.html' template_name = 'djangocms_blog/post_list.html'
paginate_by = BLOG_PAGINATION paginate_by = get_setting('PAGINATION')
view_url_name = 'djangocms_blog:posts-latest' view_url_name = 'djangocms_blog:posts-latest'
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(PostListView, self).get_context_data(**kwargs) context = super(PostListView, self).get_context_data(**kwargs)
context['TRUNCWORDS_COUNT'] = BLOG_POSTS_LIST_TRUNCWORDS_COUNT context['TRUNCWORDS_COUNT'] = get_setting('POSTS_LIST_TRUNCWORDS_COUNT')
return context return context
@ -51,7 +50,7 @@ class PostDetailView(TranslatableSlugMixin, BaseBlogView, DetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(PostDetailView, self).get_context_data(**kwargs) context = super(PostDetailView, self).get_context_data(**kwargs)
context['meta'] = self.get_object().as_meta() context['meta'] = self.get_object().as_meta()
context['use_placeholder'] = BLOG_USE_PLACEHOLDER context['use_placeholder'] = get_setting('USE_PLACEHOLDER')
setattr(self.request, BLOG_CURRENT_POST_IDENTIFIER, self.get_object()) setattr(self.request, BLOG_CURRENT_POST_IDENTIFIER, self.get_object())
return context return context
@ -63,7 +62,7 @@ class PostArchiveView(BaseBlogView, ListView):
date_field = 'date_published' date_field = 'date_published'
allow_empty = True allow_empty = True
allow_future = True allow_future = True
paginate_by = BLOG_PAGINATION paginate_by = get_setting('PAGINATION')
view_url_name = 'djangocms_blog:posts-archive' view_url_name = 'djangocms_blog:posts-archive'
def get_queryset(self): def get_queryset(self):
@ -86,7 +85,7 @@ class TaggedListView(BaseBlogView, ListView):
model = Post model = Post
context_object_name = 'post_list' context_object_name = 'post_list'
template_name = 'djangocms_blog/post_list.html' template_name = 'djangocms_blog/post_list.html'
paginate_by = BLOG_PAGINATION paginate_by = get_setting('PAGINATION')
view_url_name = 'djangocms_blog:posts-tagged' view_url_name = 'djangocms_blog:posts-tagged'
def get_queryset(self): def get_queryset(self):
@ -103,7 +102,7 @@ class AuthorEntriesView(BaseBlogView, ListView):
model = Post model = Post
context_object_name = 'post_list' context_object_name = 'post_list'
template_name = 'djangocms_blog/post_list.html' template_name = 'djangocms_blog/post_list.html'
paginate_by = BLOG_PAGINATION paginate_by = get_setting('PAGINATION')
view_url_name = 'djangocms_blog:posts-authors' view_url_name = 'djangocms_blog:posts-authors'
def get_queryset(self): def get_queryset(self):
@ -122,16 +121,13 @@ class CategoryEntriesView(BaseBlogView, ListView):
context_object_name = 'post_list' context_object_name = 'post_list'
template_name = 'djangocms_blog/post_list.html' template_name = 'djangocms_blog/post_list.html'
_category = None _category = None
paginate_by = BLOG_PAGINATION paginate_by = get_setting('PAGINATION')
view_url_name = 'djangocms_blog:posts-category' view_url_name = 'djangocms_blog:posts-category'
@property @property
def category(self): def category(self):
if not self._category: if not self._category:
language = get_language() self._category = BlogCategory.objects.active_translations(get_language(), slug=self.kwargs['category']).latest('pk')
self._category = BlogCategory._default_manager.language(language).get(
translations__language_code=language,
translations__slug=self.kwargs['category'])
return self._category return self._category
def get_queryset(self): def get_queryset(self):

View file

@ -6,3 +6,4 @@ nose>=1.3.0
django-nose>=1.2 django-nose>=1.2
flake8 flake8
djangocms-helper>=0.4 djangocms-helper>=0.4
tox>=1.8

View file

@ -36,7 +36,7 @@ setup(
], ],
include_package_data=True, include_package_data=True,
install_requires=[ install_requires=[
'django-parler>=1.0', 'django-parler>=1.1',
'django-cms>=3.0', 'django-cms>=3.0',
'django-taggit', 'django-taggit',
'django-filer', 'django-filer',

View file

@ -8,6 +8,7 @@ from cms.utils.i18n import get_language_list
from cmsplugin_filer_image.models import ThumbnailOption from cmsplugin_filer_image.models import ThumbnailOption
from django.conf import settings from django.conf import settings
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.sites.models import Site
from django.core.files import File as DjangoFile from django.core.files import File as DjangoFile
from django.http import SimpleCookie from django.http import SimpleCookie
from django.test import TestCase, RequestFactory from django.test import TestCase, RequestFactory
@ -16,8 +17,8 @@ from filer.models import File, Image
from PIL import Image as PilImage, ImageDraw from PIL import Image as PilImage, ImageDraw
from six import StringIO from six import StringIO
from djangocms_blog.models import BlogCategory, Post
from djangocms_helper.utils import create_user from djangocms_helper.utils import create_user
from djangocms_blog.models import BlogCategory, Post
User = get_user_model() User = get_user_model()
@ -37,10 +38,13 @@ class BaseTest(TestCase):
'it': [ 'it': [
{'title': u'Primo post', 'abstract': u'<p>prima riga</p>', {'title': u'Primo post', 'abstract': u'<p>prima riga</p>',
'description': u'Questa è la descrizione', 'keywords': u'keyword1, keyword2', 'description': u'Questa è la descrizione', 'keywords': u'keyword1, keyword2',
'text': u'Testo del post',}, 'text': u'Testo del post'},
{'title': u'Secondo post', 'abstract': u'<p>prima riga del secondo post</p>', {'title': u'Secondo post', 'abstract': u'<p>prima riga del secondo post</p>',
'description': u'Descrizione del secondo post', 'keywords': u'keyword3, keyword4', 'description': u'Descrizione del secondo post', 'keywords': u'keyword3, keyword4',
'text': u'Testo del secondo post'}, 'text': u'Testo del secondo post'},
{'title': u'Terzo post', 'abstract': u'<p>prima riga del terzo post</p>',
'description': u'Descrizione del terzo post', 'keywords': u'keyword5, keyword6',
'text': u'Testo del terzo post'},
], ],
'en': [ 'en': [
{'title': u'First post', 'abstract': u'<p>first line</p>', {'title': u'First post', 'abstract': u'<p>first line</p>',
@ -48,7 +52,10 @@ class BaseTest(TestCase):
'text': u'Post text'}, 'text': u'Post text'},
{'title': u'Second post', 'abstract': u'<p>second post first line</p>', {'title': u'Second post', 'abstract': u'<p>second post first line</p>',
'description': u'Second post description', 'keywords': u'keyword3, keyword4', 'description': u'Second post description', 'keywords': u'keyword3, keyword4',
'text': u'Second post text'} 'text': u'Second post text'},
{'title': u'Third post', 'abstract': u'<p>third post first line</p>',
'description': u'third post description', 'keywords': u'keyword5, keyword6',
'text': u'Third post text'}
] ]
} }
@ -58,17 +65,16 @@ class BaseTest(TestCase):
cls.user = create_user('admin', 'admin@admin.com', 'admin', is_staff=True, is_superuser=True) cls.user = create_user('admin', 'admin@admin.com', 'admin', is_staff=True, is_superuser=True)
cls.user_staff = create_user('staff', 'staff@admin.com', 'staff', is_staff=True) cls.user_staff = create_user('staff', 'staff@admin.com', 'staff', is_staff=True)
cls.user_normal = create_user('normal', 'normal@admin.com', 'normal') cls.user_normal = create_user('normal', 'normal@admin.com', 'normal')
cls.site_1 = Site.objects.get(pk=1)
cls.site_2 = Site.objects.create(domain='http://example2.com', name='example 2')
def setUp(self): def setUp(self):
activate('en') activate('en')
super(BaseTest, self).setUp() super(BaseTest, self).setUp()
self.category_1 = BlogCategory.objects.create() self.category_1 = BlogCategory.objects.create(name=u'category 1')
self.category_1.name = u'category 1' self.category_1.set_current_language('it', initialize=True)
self.category_1.save()
self.category_1.set_current_language('it')
self.category_1.name = u'categoria 1' self.category_1.name = u'categoria 1'
self.category_1.save() self.category_1.save()
self.category_1.set_current_language('en')
self.thumb_1 = ThumbnailOption.objects.create( self.thumb_1 = ThumbnailOption.objects.create(
name='base', width=100, height=100, crop=True, upscale=False name='base', width=100, height=100, crop=True, upscale=False
) )
@ -85,18 +91,27 @@ class BaseTest(TestCase):
original_filename=self.image_name, original_filename=self.image_name,
file=file_obj) file=file_obj)
def _get_post(self, data, post=None, lang='en'): def _get_post(self, data, post=None, lang='en', sites=None):
if not post: if not post:
post = Post() post_data = {
post.set_current_language(lang) 'author': self.user,
post.author = self.user 'title': data['title'],
post.title = data['title'] 'abstract': data['abstract'],
post.abstract = data['abstract'] 'meta_description': data['description'],
post.meta_description = data['description'] 'meta_keywords': data['keywords'],
post.meta_keywords = data['keywords'] }
post.save() post = Post.objects.create(**post_data)
else:
post.set_current_language(lang)
post.title = data['title']
post.abstract = data['abstract']
post.meta_description = data['description']
post.meta_keywords = data['keywords']
post.save()
post.categories.add(self.category_1) post.categories.add(self.category_1)
post.save() if sites:
for site in sites:
post.sites.add(site)
return post return post
@classmethod @classmethod
@ -104,6 +119,8 @@ class BaseTest(TestCase):
User.objects.all().delete() User.objects.all().delete()
def tearDown(self): def tearDown(self):
for post in Post.objects.all():
post.delete()
os.remove(self.filename) os.remove(self.filename)
for f in File.objects.all(): for f in File.objects.all():
f.delete() f.delete()
@ -128,6 +145,16 @@ class BaseTest(TestCase):
request.errors = StringIO() request.errors = StringIO()
return request return request
def post_request(self, page, lang, data):
request = self.request_factory.post(page.get_path(lang), data)
request.current_page = page
request.user = self.user
request.session = {}
request.cookies = SimpleCookie()
request.errors = StringIO()
request._dont_enforce_csrf_checks = True
return request
def get_page_request(self, page, user, path=None, edit=False, lang_code='en'): def get_page_request(self, page, user, path=None, edit=False, lang_code='en'):
from cms.middleware.toolbar import ToolbarMiddleware from cms.middleware.toolbar import ToolbarMiddleware
path = path or page and page.get_absolute_url() path = path or page and page.get_absolute_url()
@ -146,17 +173,16 @@ class BaseTest(TestCase):
mid.process_request(request) mid.process_request(request)
return request return request
def get_posts(self): def get_posts(self, sites=None):
post1 = self._get_post(self.data['en'][0]) post1 = self._get_post(self.data['en'][0], sites=sites)
post1 = self._get_post(self.data['it'][0], post1, 'it') post1 = self._get_post(self.data['it'][0], post1, 'it')
post1.publish = True post1.publish = True
post1.main_image = self.img post1.main_image = self.img
post1.save() post1.save()
post1.set_current_language('en') post2 = self._get_post(self.data['en'][1], sites=sites)
post2 = self._get_post(self.data['en'][1])
post2 = self._get_post(self.data['it'][1], post2, 'it') post2 = self._get_post(self.data['it'][1], post2, 'it')
post2.set_current_language('en')
post2.main_image = self.img post2.main_image = self.img
post2.save()
return post1, post2 return post1, post2

View file

@ -2,19 +2,92 @@
from cms.api import add_plugin from cms.api import add_plugin
from cms.utils.copy_plugins import copy_plugins_to from cms.utils.copy_plugins import copy_plugins_to
from cms.utils.plugins import downcast_plugins from cms.utils.plugins import downcast_plugins
from copy import deepcopy
from django.contrib import admin
from django.contrib.messages.middleware import MessageMiddleware
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils.timezone import now from django.utils.timezone import now
from django.utils.translation import get_language, override
import parler import parler
from taggit.models import Tag from taggit.models import Tag
from djangocms_blog.models import Post from djangocms_blog.models import Post
from djangocms_blog import settings from djangocms_blog.settings import get_setting
from . import BaseTest from . import BaseTest
class AdminTest(BaseTest):
def test_admin_fieldsets(self):
request = self.get_page_request('/', self.user_staff, r'/en/blog/', edit=False)
post_admin = admin.site._registry[Post]
with self.settings(BLOG_USE_PLACEHOLDER=True):
fsets = post_admin.get_fieldsets(request)
self.assertFalse('post_text' in fsets[0][1]['fields'])
with self.settings(BLOG_USE_PLACEHOLDER=False):
fsets = post_admin.get_fieldsets(request)
self.assertTrue('post_text' in fsets[0][1]['fields'])
with self.settings(BLOG_MULTISITE=True):
fsets = post_admin.get_fieldsets(request)
self.assertTrue('sites' in fsets[1][1]['fields'][0])
with self.settings(BLOG_MULTISITE=False):
fsets = post_admin.get_fieldsets(request)
self.assertFalse('sites' in fsets[1][1]['fields'][0])
request = self.get_page_request('/', self.user, r'/en/blog/', edit=False)
fsets = post_admin.get_fieldsets(request)
self.assertTrue('author' in fsets[1][1]['fields'][0])
def test_admin_auto_author(self):
page1, page2 = self.get_pages()
request = self.get_page_request('/', self.user_staff, r'/en/blog/', edit=False)
data = deepcopy(self.data['en'][0])
with self.settings(BLOG_AUTHOR_DEFAULT=True):
data['date_published_0'] = now().strftime('%Y-%m-%d')
data['date_published_1'] = now().strftime('%H:%M:%S')
data['categories'] = self.category_1.pk
request = self.post_request(page1, 'en', data=data)
msg_mid = MessageMiddleware()
msg_mid.process_request(request)
post_admin = admin.site._registry[Post]
post_admin.add_view(request)
self.assertEqual(Post.objects.count(), 1)
self.assertEqual(Post.objects.get(translations__slug='first-post').author_id, 1)
with self.settings(BLOG_AUTHOR_DEFAULT=False):
data = deepcopy(self.data['en'][1])
data['date_published_0'] = now().strftime('%Y-%m-%d')
data['date_published_1'] = now().strftime('%H:%M:%S')
data['categories'] = self.category_1.pk
request = self.post_request(page1, 'en', data=data)
msg_mid = MessageMiddleware()
msg_mid.process_request(request)
post_admin = admin.site._registry[Post]
post_admin.add_view(request)
self.assertEqual(Post.objects.count(), 2)
self.assertEqual(Post.objects.get(translations__slug='second-post').author_id, None)
with self.settings(BLOG_AUTHOR_DEFAULT='staff'):
data = deepcopy(self.data['en'][2])
data['date_published_0'] = now().strftime('%Y-%m-%d')
data['date_published_1'] = now().strftime('%H:%M:%S')
data['categories'] = self.category_1.pk
request = self.post_request(page1, 'en', data=data)
msg_mid = MessageMiddleware()
msg_mid.process_request(request)
post_admin = admin.site._registry[Post]
post_admin.add_view(request)
self.assertEqual(Post.objects.count(), 3)
self.assertEqual(Post.objects.get(translations__slug='third-post').author.username, 'staff')
class ModelsTest(BaseTest): class ModelsTest(BaseTest):
def test_model_attributes(self): def test_model_attributes(self):
@ -24,7 +97,7 @@ class ModelsTest(BaseTest):
post.save() post.save()
post.set_current_language('en') post.set_current_language('en')
meta_en = post.as_meta() meta_en = post.as_meta()
self.assertEqual(meta_en.og_type, settings.BLOG_FB_TYPE) self.assertEqual(meta_en.og_type, get_setting('FB_TYPE'))
self.assertEqual(meta_en.title, post.title) self.assertEqual(meta_en.title, post.title)
self.assertTrue(meta_en.url.endswith(post.get_absolute_url())) self.assertTrue(meta_en.url.endswith(post.get_absolute_url()))
self.assertEqual(meta_en.description, post.meta_description) self.assertEqual(meta_en.description, post.meta_description)
@ -37,27 +110,30 @@ class ModelsTest(BaseTest):
self.assertNotEqual(meta_it.title, meta_en.title) self.assertNotEqual(meta_it.title, meta_en.title)
self.assertEqual(meta_it.description, post.meta_description) self.assertEqual(meta_it.description, post.meta_description)
post.set_current_language('en') with override('en'):
kwargs = {'year': post.date_published.year, post.set_current_language(get_language())
'month': post.date_published.month, kwargs = {'year': post.date_published.year,
'day': post.date_published.day, 'month': '%02d' % post.date_published.month,
'slug': post.safe_translation_getter('slug', any_language=True)} 'day': '%02d' % post.date_published.day,
url_en = reverse('djangocms_blog:post-detail', kwargs=kwargs) 'slug': post.safe_translation_getter('slug', any_language=get_language())}
self.assertEqual(url_en, post.get_absolute_url()) url_en = reverse('djangocms_blog:post-detail', kwargs=kwargs)
post.set_current_language('it') self.assertEqual(url_en, post.get_absolute_url())
kwargs = {'year': post.date_published.year,
'month': post.date_published.month,
'day': post.date_published.day,
'slug': post.safe_translation_getter('slug', any_language=True)}
url_it = reverse('djangocms_blog:post-detail', kwargs=kwargs)
self.assertEqual(url_it, post.get_absolute_url())
self.assertNotEqual(url_it, url_en)
self.assertEqual(post.get_full_url(), 'http://example.com%s' % url_it) with override('it'):
post.set_current_language(get_language())
kwargs = {'year': post.date_published.year,
'month': '%02d' % post.date_published.month,
'day': '%02d' % post.date_published.day,
'slug': post.safe_translation_getter('slug', any_language=get_language())}
url_it = reverse('djangocms_blog:post-detail', kwargs=kwargs)
self.assertEqual(url_it, post.get_absolute_url())
self.assertNotEqual(url_it, url_en)
self.assertEqual(post.get_full_url(), 'http://example.com%s' % url_it)
self.assertEqual(post.get_image_full_url(), 'http://example.com%s' % post.main_image.url) self.assertEqual(post.get_image_full_url(), 'http://example.com%s' % post.main_image.url)
self.assertEqual(post.thumbnail_options(), settings.BLOG_IMAGE_THUMBNAIL_SIZE) self.assertEqual(post.thumbnail_options(), get_setting('IMAGE_THUMBNAIL_SIZE'))
self.assertEqual(post.full_image_options(), settings.BLOG_IMAGE_FULL_SIZE) self.assertEqual(post.full_image_options(), get_setting('IMAGE_FULL_SIZE'))
post.main_image_thumbnail = self.thumb_1 post.main_image_thumbnail = self.thumb_1
post.main_image_full = self.thumb_2 post.main_image_full = self.thumb_2
@ -213,3 +289,17 @@ class ModelsTest(BaseTest):
copy_plugins_to(plugins, post2.content) copy_plugins_to(plugins, post2.content)
new = downcast_plugins(post2.content.cmsplugin_set.all()) new = downcast_plugins(post2.content.cmsplugin_set.all())
self.assertEqual(set(new[0].authors.all()), set([self.user])) self.assertEqual(set(new[0].authors.all()), set([self.user]))
def test_multisite(self):
with override('en'):
post1 = self._get_post(self.data['en'][0], sites=(self.site_1,))
post2 = self._get_post(self.data['en'][1], sites=(self.site_2,))
post3 = self._get_post(self.data['en'][2], sites=(self.site_2, self.site_1))
self.assertEqual(len(Post.objects.all()), 3)
with self.settings(**{'SITE_ID': self.site_1.pk}):
self.assertEqual(len(Post.objects.all().on_site()), 2)
self.assertEqual(set(list(Post.objects.all().on_site())), set([post1, post3]))
with self.settings(**{'SITE_ID': self.site_2.pk}):
self.assertEqual(len(Post.objects.all().on_site()), 2)
self.assertEqual(set(list(Post.objects.all().on_site())), set([post2, post3]))

View file

@ -3,7 +3,7 @@ from django.contrib.auth.models import AnonymousUser
from django.http import Http404 from django.http import Http404
from django.utils.translation import activate from django.utils.translation import activate
from django.utils.timezone import now from django.utils.timezone import now
from djangocms_blog.models import Post from parler.utils.context import switch_language
from djangocms_blog.feeds import LatestEntriesFeed, TagFeed from djangocms_blog.feeds import LatestEntriesFeed, TagFeed
from djangocms_blog.sitemaps import BlogSitemap from djangocms_blog.sitemaps import BlogSitemap
from djangocms_blog.views import (PostListView, PostDetailView, from djangocms_blog.views import (PostListView, PostDetailView,
@ -27,6 +27,14 @@ class ViewTest(BaseTest):
self.assertEqual(list(view_obj.get_queryset()), [post1]) self.assertEqual(list(view_obj.get_queryset()), [post1])
request = self.get_page_request(page1, self.user, r'/en/blog/', edit=False) request = self.get_page_request(page1, self.user, r'/en/blog/', edit=False)
activate('en')
view_obj.request = request
view_obj.kwargs = {}
qs = view_obj.get_queryset()
self.assertEqual(qs.count(), 1)
self.assertEqual(set(qs), set([post1]))
request = self.get_page_request(page1, self.user, r'/en/blog/', edit=True)
view_obj.request = request view_obj.request = request
self.assertEqual(set(view_obj.get_queryset()), set([post1, post2])) self.assertEqual(set(view_obj.get_queryset()), set([post1, post2]))
@ -41,7 +49,7 @@ class ViewTest(BaseTest):
response = view_obj.render_to_response(context) response = view_obj.render_to_response(context)
self.assertContains(response, context['post_list'][0].get_absolute_url()) self.assertContains(response, context['post_list'][0].get_absolute_url())
request = self.get_page_request(page1, self.user, r'/it/blog/', lang_code='it', edit=False) request = self.get_page_request(page1, self.user, r'/it/blog/', lang_code='it', edit=True)
activate('it') activate('it')
view_obj.request = request view_obj.request = request
view_obj.object_list = view_obj.get_queryset() view_obj.object_list = view_obj.get_queryset()
@ -54,34 +62,33 @@ class ViewTest(BaseTest):
page1, page2 = self.get_pages() page1, page2 = self.get_pages()
post1, post2 = self.get_posts() post1, post2 = self.get_posts()
request = self.get_page_request(page1, AnonymousUser(), r'/en/blog/', edit=False) with switch_language(post1, 'en'):
activate('en') request = self.get_page_request(page1, AnonymousUser(), r'/en/blog/', edit=False)
view_obj = PostDetailView() view_obj = PostDetailView()
view_obj.request = request view_obj.request = request
with self.assertRaises(Http404): with self.assertRaises(Http404):
view_obj.kwargs = {'slug': 'not-existing'} view_obj.kwargs = {'slug': 'not-existing'}
post_obj = view_obj.get_object()
view_obj.kwargs = {'slug': post1.slug}
post_obj = view_obj.get_object() post_obj = view_obj.get_object()
self.assertEqual(post_obj, post1)
self.assertEqual(post_obj.language_code, 'en')
view_obj.kwargs = {'slug': post1.slug} with switch_language(post1, 'it'):
post_obj = view_obj.get_object() request = self.get_page_request(page1, AnonymousUser(), r'/it/blog/', lang_code='it', edit=False)
self.assertEqual(post_obj, post1) view_obj.request = request
self.assertEqual(post_obj.language_code, 'en') view_obj.kwargs = {'slug': post1.slug}
post_obj = view_obj.get_object()
self.assertEqual(post_obj, post1)
self.assertEqual(post_obj.language_code, 'it')
request = self.get_page_request(page1, AnonymousUser(), r'/it/blog/', lang_code='it', edit=False) view_obj.object = post_obj
activate('it') context = view_obj.get_context_data()
post1.set_current_language('it') self.assertEqual(context['post'], post1)
view_obj.request = request self.assertEqual(context['post'].language_code, 'it')
view_obj.kwargs = {'slug': post1.slug} self.assertTrue(context['meta'])
post_obj = view_obj.get_object()
self.assertEqual(post_obj, post1)
self.assertEqual(post_obj.language_code, 'it')
view_obj.object = post_obj
context = view_obj.get_context_data()
self.assertEqual(context['post'], post1)
self.assertEqual(context['post'].language_code, 'it')
self.assertTrue(context['meta'])
def test_post_archive_view(self): def test_post_archive_view(self):
page1, page2 = self.get_pages() page1, page2 = self.get_pages()
@ -106,7 +113,7 @@ class ViewTest(BaseTest):
page1, page2 = self.get_pages() page1, page2 = self.get_pages()
post1, post2 = self.get_posts() post1, post2 = self.get_posts()
request = self.get_page_request(page1, self.user, r'/en/blog/', edit=False) request = self.get_page_request(page1, self.user, r'/en/blog/', edit=True)
activate('en') activate('en')
view_obj = CategoryEntriesView() view_obj = CategoryEntriesView()
view_obj.request = request view_obj.request = request
@ -129,7 +136,7 @@ class ViewTest(BaseTest):
page1, page2 = self.get_pages() page1, page2 = self.get_pages()
post1, post2 = self.get_posts() post1, post2 = self.get_posts()
request = self.get_page_request(page1, self.user, r'/en/blog/', edit=False) request = self.get_page_request(page1, self.user, r'/en/blog/', edit=True)
activate('en') activate('en')
view_obj = AuthorEntriesView() view_obj = AuthorEntriesView()
view_obj.request = request view_obj.request = request
@ -156,7 +163,7 @@ class ViewTest(BaseTest):
post2.tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8') post2.tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8')
post2.save() post2.save()
request = self.get_page_request(page1, self.user, r'/en/blog/', edit=False) request = self.get_page_request(page1, self.user, r'/en/blog/', edit=True)
activate('en') activate('en')
view_obj = TaggedListView() view_obj = TaggedListView()
view_obj.request = request view_obj.request = request

35
tox.ini
View file

@ -1,32 +1,13 @@
[tox] [tox]
envlist = py26dj15, py26dj16, py27dj15, py27dj16 envlist = {py26,py27}-django{15,16}
[testenv] [testenv]
commands = djangocms-helper djangocms_blog test --cms --nose basepython =
py26: python2.6
py27: python2.7
deps = deps =
django15: Django>=1.5,<1.6
django16: Django>=1.6,<1.7
py26: unittest2
-r{toxinidir}/requirements-test.txt -r{toxinidir}/requirements-test.txt
commands = djangocms-helper djangocms_blog test --cms --nose
[testenv:py26dj15]
basepython=python2.6
deps =
django<1.6
{[testenv]deps}
[testenv:py26dj16]
basepython=python2.6
deps =
django<1.7
{[testenv]deps}
[testenv:py27dj15]
basepython=python2.7
deps =
django<1.6
{[testenv]deps}
[testenv:py27dj16]
basepython=python2.7
deps =
django<1.7
{[testenv]deps}