From 2a32f17b0b7e2ec1b5c680c91634c33e73388527 Mon Sep 17 00:00:00 2001 From: Kostas Papadimitriou Date: Tue, 10 Jul 2012 10:47:34 +0300 Subject: [PATCH] Cloudcmsfaq services as primary category Use cloudcmsfaq service model as the primary category of a question --- .../0005_auto__add_field_question_service.py | 181 ++++++++++++++++++++ cloudcmsfaq/admin.py | 7 +- cloudcmsfaq/models.py | 22 +-- cloudcmsfaq/templates/cloudcmsfaq/archive.html | 22 ++- cloudcmsfaq/urls.py | 4 +- cloudcmsfaq/views.py | 16 +- 6 files changed, 222 insertions(+), 30 deletions(-) create mode 100644 cloudcms/migrate/cloudcmsfaq/0005_auto__add_field_question_service.py diff --git a/cloudcms/migrate/cloudcmsfaq/0005_auto__add_field_question_service.py b/cloudcms/migrate/cloudcmsfaq/0005_auto__add_field_question_service.py new file mode 100644 index 0000000..b670546 --- /dev/null +++ b/cloudcms/migrate/cloudcmsfaq/0005_auto__add_field_question_service.py @@ -0,0 +1,181 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'Question.service' + db.add_column('cloudcmsfaq_question', 'service', + self.gf('django.db.models.fields.related.ForeignKey')(related_name='faqs', null=True, to=orm['cloudcms.Service']), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'Question.service' + db.delete_column('cloudcmsfaq_question', 'service_id') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + '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': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + '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', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + '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', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'cloudcms.application': { + 'Meta': {'object_name': 'Application'}, + 'app_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'code': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'extra_styles': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'facebook_username': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'favicon': ('feincms.module.medialibrary.fields.MediaFileForeignKey', [], {'blank': 'True', 'related_name': "'as_favicon'", 'null': 'True', 'to': "orm['medialibrary.MediaFile']"}), + 'footer_bottom': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'footer_top': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'index_url': ('django.db.models.fields.CharField', [], {'default': "'/'", 'max_length': '255'}), + 'linked_in_username': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'logo': ('feincms.module.medialibrary.fields.MediaFileForeignKey', [], {'to': "orm['medialibrary.MediaFile']", 'null': 'True', 'blank': 'True'}), + 'show_twitter_feed_on_top': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'twitter_username': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}) + }, + 'cloudcms.service': { + 'Meta': {'ordering': "['-ordering']", 'object_name': 'Service'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ordering': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}) + }, + 'cloudcmsfaq.category': { + 'Meta': {'ordering': "['-ordering']", 'object_name': 'Category'}, + 'display_on_menu': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ordering': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}) + }, + 'cloudcmsfaq.categorytranslation': { + 'Meta': {'ordering': "['title']", 'object_name': 'CategoryTranslation'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '250', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'language_code': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '10'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'translations'", 'to': "orm['cloudcmsfaq.Category']"}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'cloudcmsfaq.imagecontent': { + 'Meta': {'ordering': "['ordering']", 'object_name': 'ImageContent', 'db_table': "'cloudcmsfaq_question_imagecontent'"}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), + 'ordering': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'imagecontent_set'", 'to': "orm['cloudcmsfaq.Question']"}), + 'position': ('django.db.models.fields.CharField', [], {'default': "'default'", 'max_length': '10'}), + 'region': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'cloudcmsfaq.question': { + 'Meta': {'ordering': "['-published_on']", 'object_name': 'Question'}, + 'application': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'faqs'", 'symmetrical': 'False', 'to': "orm['cloudcms.Application']"}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'faqs'", 'to': "orm['auth.User']"}), + 'category': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'faqs'", 'to': "orm['cloudcmsfaq.Category']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_featured': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'language': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'last_changed': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'published_on': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'null': 'True', 'blank': 'True'}), + 'service': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'faqs'", 'null': 'True', 'to': "orm['cloudcms.Service']"}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '100'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'cloudcmsfaq.rawcontent': { + 'Meta': {'ordering': "['ordering']", 'object_name': 'RawContent', 'db_table': "'cloudcmsfaq_question_rawcontent'"}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ordering': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rawcontent_set'", 'to': "orm['cloudcmsfaq.Question']"}), + 'region': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'text': ('django.db.models.fields.TextField', [], {'blank': 'True'}) + }, + 'cloudcmsfaq.richtextcontent': { + 'Meta': {'ordering': "['ordering']", 'object_name': 'RichTextContent', 'db_table': "'cloudcmsfaq_question_richtextcontent'"}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ordering': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'richtextcontent_set'", 'to': "orm['cloudcmsfaq.Question']"}), + 'region': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'text': ('django.db.models.fields.TextField', [], {'blank': 'True'}) + }, + 'cloudcmsfaq.sectioncontent': { + 'Meta': {'ordering': "['ordering']", 'object_name': 'SectionContent', 'db_table': "'cloudcmsfaq_question_sectioncontent'"}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mediafile': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'cloudcmsfaq_sectioncontent_set'", 'null': 'True', 'to': "orm['medialibrary.MediaFile']"}), + 'ordering': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sectioncontent_set'", 'to': "orm['cloudcmsfaq.Question']"}), + 'region': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'richtext': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), + 'type': ('django.db.models.fields.CharField', [], {'default': "'block'", 'max_length': '10'}) + }, + 'cloudcmsfaq.templatecontent': { + 'Meta': {'ordering': "['ordering']", 'object_name': 'TemplateContent', 'db_table': "'cloudcmsfaq_question_templatecontent'"}, + 'filename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ordering': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'templatecontent_set'", 'to': "orm['cloudcmsfaq.Question']"}), + 'region': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + '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'}), + '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'}) + }, + 'medialibrary.category': { + 'Meta': {'ordering': "['parent__title', 'title']", 'object_name': 'Category'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['medialibrary.Category']"}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '150'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'}) + }, + 'medialibrary.mediafile': { + 'Meta': {'object_name': 'MediaFile'}, + 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['medialibrary.Category']", 'null': 'True', 'blank': 'True'}), + 'copyright': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255'}), + 'file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}) + }, + 'sites.site': { + 'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"}, + 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + } + } + + complete_apps = ['cloudcmsfaq'] \ No newline at end of file diff --git a/cloudcmsfaq/admin.py b/cloudcmsfaq/admin.py index d5b18a6..a37ea15 100644 --- a/cloudcmsfaq/admin.py +++ b/cloudcmsfaq/admin.py @@ -44,9 +44,9 @@ CategoryTranslationInline = admin_translationinline(CategoryTranslation, class QuestionAdmin(item_editor.ItemEditor): date_hierarchy = 'published_on' - list_display = ['title', 'is_active', 'published_on', 'author'] - list_editable = ['is_active',] - list_filter = ['is_active', 'is_featured', 'category', 'author'] + list_display = ['title', 'is_active', 'published_on', 'author', 'service', 'category'] + list_editable = ['is_active', 'service', 'category'] + list_filter = ['is_active', 'is_featured', 'service', 'category', 'author'] search_fields = ['title', 'slug'] prepopulated_fields = { 'slug': ('title',), @@ -59,6 +59,7 @@ class QuestionAdmin(item_editor.ItemEditor): ('title', 'slug'), 'author', 'application', + 'service', 'category', ] }], diff --git a/cloudcmsfaq/models.py b/cloudcmsfaq/models.py index 7f47d36..175cddb 100644 --- a/cloudcmsfaq/models.py +++ b/cloudcmsfaq/models.py @@ -95,11 +95,6 @@ class CategoryTranslation(translations.Translation(Category)): def __unicode__(self): return self.title - def get_absolute_url(self): - return reverse('cloudcmsfaq_category_archive', 'cloudcmsfaq.urls', (), { - 'category': self.slug, - }) - def save(self, *args, **kwargs): if not self.slug: self.slug = slugify(self.title) @@ -142,6 +137,9 @@ class Question(Base): help_text=_('Will be filled in automatically when question gets published.')) last_changed = models.DateTimeField(_('last change'), auto_now=True, editable=False) + service = models.ForeignKey('cloudcms.Service', verbose_name=_('service'), + related_name='faqs', null=True, blank=False) + category = models.ForeignKey(Category, verbose_name=_('category'), related_name='faqs', null=False, blank=False) @@ -149,7 +147,7 @@ class Question(Base): class Meta: get_latest_by = 'published_on' - ordering = ['-published_on'] + ordering = ['service', 'category', '-published_on'] verbose_name = _('faq') verbose_name_plural = _('faqs') @@ -160,7 +158,7 @@ class Question(Base): try: r = reverse('cloudcmsfaq_question_detail', 'cloudcmsfaq.urls', (), { - 'category': self.category.translation.slug, + 'service': self.service.translation.slug, 'slug': self.slug, }) except Exception, e: @@ -183,7 +181,7 @@ class Question(Base): # Feincms navigation extension -class FaqCategoriesNavigationExtension(NavigationExtension): +class FaqServicesNavigationExtension(NavigationExtension): """ Navigation extension for FeinCMS which lists all categories that user wants to include in global site navigation. @@ -192,10 +190,12 @@ class FaqCategoriesNavigationExtension(NavigationExtension): name = _('faq categories') def children(self, page, **kwargs): - for category in Category.objects.filter(display_on_menu=True): - url='%scategory/%s/' % (page.get_absolute_url(), category.translation.slug) + from cloudcms.models import Service + + for service in Service.objects.filter(display_on_menu=True): + url='%sservice/%s/' % (page.get_absolute_url(), service.translation.slug) yield PagePretender( - title=category.translation.title, + title=service.translation.title, tree_id=page.tree_id, url=url, lft=0, diff --git a/cloudcmsfaq/templates/cloudcmsfaq/archive.html b/cloudcmsfaq/templates/cloudcmsfaq/archive.html index 9230a9f..c8e3a44 100644 --- a/cloudcmsfaq/templates/cloudcmsfaq/archive.html +++ b/cloudcmsfaq/templates/cloudcmsfaq/archive.html @@ -1,15 +1,23 @@ -{% load applicationcontent_tags pagination_tags i18n %} +{% load applicationcontent_tags pagination_tags i18n cloudcms_tags %}
- {% for category in categories %} + {% for service in services %}
-

{{ category.translation.title|upper }}

+

{{ service.translation.title|upper }}

    - {% for q in category.faqs.active %} -
  • - {{ q.title }} -
  • +
  • + {% for category, questions in service|get_service_faqs %} +

    {{ category.translation.title|upper }}

    +
      + {% for q in questions %} +
    • + {{ q.title }} +
    • + {% endfor %} +
      +
    {% endfor %} +
{% endfor %} diff --git a/cloudcmsfaq/urls.py b/cloudcmsfaq/urls.py index c3e28bf..10b66bc 100644 --- a/cloudcmsfaq/urls.py +++ b/cloudcmsfaq/urls.py @@ -40,8 +40,8 @@ admin.autodiscover() urlpatterns = patterns('cloudcmsfaq.views', url(r'^$', 'index', name='cloudcmsfaq_entries_archive'), - url(r'^category/(?P\w+)/$', 'archive', name='cloudcmsfaq_category_archive'), - url(r'^(?P[-\w]+)/(?P[-\w]+)/$', + url(r'^service/(?P\w+)/$', 'archive', name='cloudcmsfaq_category_archive'), + url(r'^(?P[\w]+)-(?P[-\w]+)/$', 'detail', name='cloudcmsfaq_question_detail'), ) diff --git a/cloudcmsfaq/views.py b/cloudcmsfaq/views.py index 9c75140..8404454 100644 --- a/cloudcmsfaq/views.py +++ b/cloudcmsfaq/views.py @@ -36,7 +36,7 @@ from django.conf import settings from django.views.generic.simple import direct_to_template from django.http import HttpResponseRedirect, Http404 -from cloudcms.models import Application +from cloudcms.models import Application, Service from cloudcmsfaq.models import Question, Category, CategoryTranslation def index(request): @@ -47,17 +47,19 @@ def archive(request): Display entries list """ app = Application.current() - categories = Category.objects.all() + services = Service.objects.all() + return direct_to_template(request, - "cloudcmsfaq/archive.html", {'categories': categories}) + "cloudcmsfaq/archive.html", {'services': services}) -def detail(request, category, slug): +def detail(request, service, slug): """ Display detailed question. """ entry = Question.objects.get(slug=slug) - categories = Category.objects.filter(pk=entry.category.pk) + services = Service.objects.filter(pk=entry.service.pk) + return direct_to_template(request, - "cloudcmsfaq/detail.html", {'question': entry, - 'categories': categories}) + "cloudcmsfaq/detail.html", {'question': entry, + 'services': services}) -- 1.7.10.4