Merge pull request #223 from nephila/feature/knocker
[WiP] Add knocker support
This commit is contained in:
commit
bbaa8aca6f
4 changed files with 81 additions and 6 deletions
|
@ -3,6 +3,11 @@
|
||||||
History
|
History
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
0.7.1 (unreleased)
|
||||||
|
++++++++++++++++++
|
||||||
|
|
||||||
|
* Add django-knocker integration
|
||||||
|
|
||||||
0.7.0 (2016-03-19)
|
0.7.0 (2016-03-19)
|
||||||
++++++++++++++++++
|
++++++++++++++++++
|
||||||
|
|
||||||
|
|
|
@ -357,6 +357,15 @@ hae been reported; to handle these cases gracefully, the exception is swallowed
|
||||||
when Django ``DEBUG == True`` avoiding breaking production websites. In these cases they
|
when Django ``DEBUG == True`` avoiding breaking production websites. In these cases they
|
||||||
wizard may not show up, but the rest will work as intended.
|
wizard may not show up, but the rest will work as intended.
|
||||||
|
|
||||||
|
django-knocker
|
||||||
|
++++++++++++++
|
||||||
|
|
||||||
|
``djangocms-blog`` is integrated with `django-knocker <https://github.com/nephila/django-knocker>`_
|
||||||
|
to provide real time desktop notifications.
|
||||||
|
|
||||||
|
See `django-knocker documentation <https://django-knocker.readthedocs.org/>`_ for how to configure
|
||||||
|
knocker.
|
||||||
|
|
||||||
.. _settings:
|
.. _settings:
|
||||||
|
|
||||||
Global Settings
|
Global Settings
|
||||||
|
|
|
@ -33,6 +33,15 @@ except ImportError:
|
||||||
from cmsplugin_filer_image.models import ThumbnailOption # NOQA
|
from cmsplugin_filer_image.models import ThumbnailOption # NOQA
|
||||||
thumbnail_model = 'cmsplugin_filer_image.ThumbnailOption'
|
thumbnail_model = 'cmsplugin_filer_image.ThumbnailOption'
|
||||||
|
|
||||||
|
try:
|
||||||
|
from knocker.mixins import KnockerModel
|
||||||
|
except ImportError:
|
||||||
|
class KnockerModel(object):
|
||||||
|
"""
|
||||||
|
Stub class if django-knocker is not installed
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class BlogCategory(TranslatableModel):
|
class BlogCategory(TranslatableModel):
|
||||||
|
@ -91,7 +100,7 @@ class BlogCategory(TranslatableModel):
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class Post(ModelMeta, TranslatableModel):
|
class Post(KnockerModel, ModelMeta, TranslatableModel):
|
||||||
"""
|
"""
|
||||||
Blog post
|
Blog post
|
||||||
"""
|
"""
|
||||||
|
@ -188,6 +197,11 @@ class Post(ModelMeta, TranslatableModel):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.safe_translation_getter('title')
|
return self.safe_translation_getter('title')
|
||||||
|
|
||||||
|
def save_translation(self, translation, *args, **kwargs):
|
||||||
|
if not translation.slug and translation.title:
|
||||||
|
translation.slug = slugify(translation.title)
|
||||||
|
super(Post, self).save_translation(translation, *args, **kwargs)
|
||||||
|
|
||||||
def get_absolute_url(self, lang=None):
|
def get_absolute_url(self, lang=None):
|
||||||
if not lang:
|
if not lang:
|
||||||
lang = get_language()
|
lang = get_language()
|
||||||
|
@ -227,11 +241,6 @@ class Post(ModelMeta, TranslatableModel):
|
||||||
data = value
|
data = value
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def save_translation(self, translation, *args, **kwargs):
|
|
||||||
if not translation.slug and translation.title:
|
|
||||||
translation.slug = slugify(translation.title)
|
|
||||||
super(Post, self).save_translation(translation, *args, **kwargs)
|
|
||||||
|
|
||||||
def get_title(self):
|
def get_title(self):
|
||||||
title = self.safe_translation_getter('meta_title', any_language=True)
|
title = self.safe_translation_getter('meta_title', any_language=True)
|
||||||
if not title:
|
if not title:
|
||||||
|
@ -285,6 +294,16 @@ class Post(ModelMeta, TranslatableModel):
|
||||||
def get_full_url(self):
|
def get_full_url(self):
|
||||||
return self.build_absolute_uri(self.get_absolute_url())
|
return self.build_absolute_uri(self.get_absolute_url())
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_published(self):
|
||||||
|
"""
|
||||||
|
Checks wether the blog post is *really* published by checking publishing dates too
|
||||||
|
"""
|
||||||
|
return (self.publish and
|
||||||
|
(self.date_published and self.date_published <= timezone.now()) and
|
||||||
|
(self.date_published_end is None or self.date_published_end > timezone.now())
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class BasePostPlugin(CMSPlugin):
|
class BasePostPlugin(CMSPlugin):
|
||||||
app_config = AppHookConfigField(
|
app_config = AppHookConfigField(
|
||||||
|
|
|
@ -3,6 +3,7 @@ from __future__ import absolute_import, print_function, unicode_literals
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
import parler
|
import parler
|
||||||
from cms.api import add_plugin
|
from cms.api import add_plugin
|
||||||
|
@ -335,6 +336,47 @@ class ModelsTest(BaseTest):
|
||||||
post.meta_title = 'meta title'
|
post.meta_title = 'meta title'
|
||||||
self.assertEqual(post.get_title(), 'meta title')
|
self.assertEqual(post.get_title(), 'meta title')
|
||||||
|
|
||||||
|
# Assess is_published property
|
||||||
|
post.publish = False
|
||||||
|
post.save()
|
||||||
|
self.assertFalse(post.is_published)
|
||||||
|
|
||||||
|
post.publish = True
|
||||||
|
post.date_published = now() + timedelta(days=1)
|
||||||
|
post.date_published_end = None
|
||||||
|
post.save()
|
||||||
|
self.assertFalse(post.is_published)
|
||||||
|
|
||||||
|
post.publish = True
|
||||||
|
post.date_published = now() - timedelta(days=1)
|
||||||
|
post.date_published_end = now() - timedelta(minutes=1)
|
||||||
|
post.save()
|
||||||
|
self.assertFalse(post.is_published)
|
||||||
|
|
||||||
|
post.publish = True
|
||||||
|
post.date_published = now() - timedelta(days=1)
|
||||||
|
post.date_published_end = None
|
||||||
|
post.save()
|
||||||
|
self.assertTrue(post.is_published)
|
||||||
|
|
||||||
|
post.publish = True
|
||||||
|
post.date_published = now() - timedelta(days=1)
|
||||||
|
post.date_published_end = now() + timedelta(minutes=1)
|
||||||
|
post.save()
|
||||||
|
self.assertTrue(post.is_published)
|
||||||
|
|
||||||
|
post.publish = False
|
||||||
|
post.date_published = now() - timedelta(days=1)
|
||||||
|
post.date_published_end = None
|
||||||
|
post.save()
|
||||||
|
self.assertFalse(post.is_published)
|
||||||
|
|
||||||
|
post.publish = False
|
||||||
|
post.date_published = now() - timedelta(days=1)
|
||||||
|
post.date_published_end = now() + timedelta(minutes=1)
|
||||||
|
post.save()
|
||||||
|
self.assertFalse(post.is_published)
|
||||||
|
|
||||||
def test_urls(self):
|
def test_urls(self):
|
||||||
self.get_pages()
|
self.get_pages()
|
||||||
post = self._get_post(self._post_data[0]['en'])
|
post = self._get_post(self._post_data[0]['en'])
|
||||||
|
|
Loading…
Reference in a new issue