Correct category link in blog post metadata
[snf-cloudcms] / cloudcmsblog / models.py
index 684f9d5..d119e0b 100644 (file)
@@ -1,21 +1,62 @@
+# Copyright 2012 GRNET S.A. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or
+# without modification, are permitted provided that the following
+# conditions are met:
+#
+#   1. Redistributions of source code must retain the above
+#      copyright notice, this list of conditions and the following
+#      disclaimer.
+#
+#   2. Redistributions in binary form must reproduce the above
+#      copyright notice, this list of conditions and the following
+#      disclaimer in the documentation and/or other materials
+#      provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# The views and conclusions contained in the software and
+# documentation are those of the authors and should not be
+# interpreted as representing official policies, either expressed
+# or implied, of GRNET S.A.
+
+
 from datetime import datetime
 
 from django.db import models
 from django.conf import settings
 from django.contrib.auth.models import User
 from django.utils.translation import ugettext_lazy as _, ugettext, ungettext
+from django.template.loader import render_to_string
+from django.core import urlresolvers
 
 from feincms import translations
 from feincms.models import Base
+from feincms.module.page.models import Page
 from feincms.content.richtext.models import RichTextContent
 from feincms.content.section.models import SectionContent
+from feincms.content.application.models import reverse
 from feincms.module.medialibrary.fields import MediaFileForeignKey
 from feincms.module.medialibrary.models import MediaFile
 from feincms.module.page.extensions.navigation import NavigationExtension
 from feincms.module.page.extensions.navigation import PagePretender
+from feincms.content.application.models import ApplicationContent
 
-from cloudcms.models import Application
+from cloudcms.cms_utils import get_app_page
 
+# monkeypatch django reverse (feincms 1.5+ solves this issue)
+urlresolvers.reverse = reverse
 
 class Category(models.Model, translations.TranslatedObjectMixin):
     """
@@ -32,11 +73,13 @@ class Category(models.Model, translations.TranslatedObjectMixin):
 
     objects = translations.TranslatedObjectManager()
 
+    def entries_count(self):
+        return self.blogentries.count()
+
     def __unicode__(self):
         trans = translations.TranslatedObjectMixin.__unicode__(self)
         return trans or _('Unnamed category')
 
-
 class CategoryTranslation(translations.Translation(Category)):
     """
     Category translation
@@ -53,11 +96,23 @@ class CategoryTranslation(translations.Translation(Category)):
     def __unicode__(self):
         return self.title
 
-    @models.permalink
     def get_absolute_url(self):
-        return ('cloudcmsblog_entries_archive', (), {
+        r = reverse('cloudcmsblog_entries_archive', 'cloudcmsblog.urls', (), {
             'category': self.slug,
-            })
+        })
+
+        # ugly hack to fix proper application reverse url
+        BLOG_URL = ""
+        try:
+            BLOG_URL = get_blog_page().get_navigation_url()
+        except Exception, e:
+            print e
+
+        if r.startswith(BLOG_URL):
+            return r
+        else:
+            return BLOG_URL + r.lstrip('/')
+
 
     def save(self, *args, **kwargs):
         if not self.slug:
@@ -71,6 +126,16 @@ class EntryManager(models.Manager):
     def active(self):
         return self.filter(is_active=True)
 
+    def latest(self, limit=3):
+        return self.filter()[:limit]
+
+
+def get_blog_page():
+    """
+    Returns Page model that has been associated with blog application
+    """
+    return get_app_page(Page, "cloudcmsblog")
+
 class Entry(Base):
     """
     Blog post entry
@@ -86,7 +151,7 @@ class Entry(Base):
     intro_text = models.TextField(max_length=255,
             help_text="Displayed in list views", blank=True)
     image = MediaFileForeignKey(MediaFile, null=True, blank=True)
-    application = models.ManyToManyField(Application,
+    application = models.ManyToManyField('cloudcms.Application',
             related_name="blogentries",
             verbose_name=_('application'))
 
@@ -108,15 +173,32 @@ class Entry(Base):
     def __unicode__(self):
         return self.title
 
-    @models.permalink
     def get_absolute_url(self):
-        return ('cloudcmsblog_entry_detail', (), {
-            'year': self.published_on.strftime('%Y'),
-            'month': self.published_on.strftime('%m'),
-            'day': self.published_on.strftime('%d'),
-            'slug': self.slug,
-            })
-
+        try:
+            r = reverse('cloudcmsblog_entry_detail', 'cloudcmsblog.urls', (),
+                    {
+                    'year': self.published_on.strftime('%Y'),
+                    'month': self.published_on.strftime('%m'),
+                    'day': self.published_on.strftime('%d'),
+                    'slug': self.slug,
+                    })
+        except Exception,e:
+            pass
+
+        # ugly hack to fix proper application reverse url
+        BLOG_URL = ""
+        try:
+            BLOG_URL = get_blog_page().get_navigation_url()
+        except Exception, e:
+            print e
+
+        if r.startswith(BLOG_URL):
+            return r
+        else:
+            return BLOG_URL + r.lstrip('/')
+
+    def back_url(self):
+        return get_blog_page().get_navigation_url()
 
 # Feincms navigation extension
 class BlogCategoriesNavigationExtension(NavigationExtension):
@@ -136,6 +218,23 @@ class BlogCategoriesNavigationExtension(NavigationExtension):
                 url=url,
                 lft=0,
                 rght=0,
+                level=page.level + 1, # blog categories are nested, assign correct level
                 slug=category.translation.slug,
             )
 
+
+# Feincms content abstract models
+class LatestEntries(models.Model):
+    title = models.CharField(max_length=255)
+    limit = models.PositiveIntegerField(default=3)
+    display_text = models.BooleanField(default=False)
+
+    class Meta:
+        abstract = True
+        verbose_name = _('Latest blog entries')
+        verbose_name_plural = _('Latest blog entries')
+
+    def render(self, **kwargs):
+        return render_to_string(['content/latest_blog.html'], {'posts':
+            Entry.objects.latest(self.limit), 'content': self})
+