From efa46e14377e7284d10f3ac27166adf68fcc77b9 Mon Sep 17 00:00:00 2001 From: Olivier Le Brouster <olivier.le-brouster@webu.coop> Date: Tue, 22 Apr 2014 16:41:41 +0200 Subject: [PATCH] initial commit --- .gitignore | 5 + AUTHORS | 3 + LICENSE | 25 + MANIFEST.in | 12 + README.md | 51 ++ ROADMAP.md | 51 ++ TESTING.md | 25 + newsbox/__init__.py | 3 + newsbox/admin.py | 325 +++++++ newsbox/locale/fr/LC_MESSAGES/django.mo | Bin 0 -> 4568 bytes newsbox/locale/fr/LC_MESSAGES/django.po | 270 ++++++ newsbox/migrations/__init__.py | 0 newsbox/models.py | 268 ++++++ newsbox/templates/newsbox/detail.html | 22 + newsbox/templates/newsbox/list.html | 74 ++ newsbox/templatetags/__init__.py | 0 .../templatetags/get_placeholder_content.py | 54 ++ newsbox/urls.py | 72 ++ newsbox/utils.py | 5 + newsbox/views.py | 114 +++ newsbox_cms/__init__.py | 0 newsbox_cms/admin.py | 139 +++ newsbox_cms/cms_plugins.py | 62 ++ newsbox_cms/locale/fr/LC_MESSAGES/django.mo | Bin 0 -> 1538 bytes newsbox_cms/locale/fr/LC_MESSAGES/django.po | 84 ++ newsbox_cms/models.py | 62 ++ .../static/newsbox_cms/custom_model.css | 11 + .../templates/newsbox_cms/detail-cms.html | 22 + .../templates/newsbox_cms/list-cms.html | 18 + newsbox_hvad/__init__.py | 0 newsbox_hvad/admin.py | 78 ++ newsbox_hvad/models.py | 84 ++ newsbox_hvad/urls.py | 10 + newsbox_hvad/views.py | 13 + setup.py | 42 + test_requirements/django-1.6.txt | 3 + test_requirements/django-1.6_cms-3.0.txt | 37 + test_requirements/requirements_base.txt | 3 + tests/myapp/README.md | 90 ++ tests/myapp/__init__.py | 1 + tests/myapp/admin.py | 45 + tests/myapp/fixtures/tests_data.json | 632 +++++++++++++ tests/myapp/models.py | 33 + tests/myapp/tests.py | 174 ++++ tests/myapp/urls.py | 22 + tests/myapp_all/__init__.py | 1 + tests/myapp_all/admin.py | 37 + tests/myapp_all/cms_app.py | 12 + tests/myapp_all/cms_plugins.py | 15 + tests/myapp_all/fixtures/tests_data.json | 835 +++++++++++++++++ tests/myapp_all/models.py | 36 + tests/myapp_all/templates/base.html | 13 + tests/myapp_all/templates/list-cms.html | 1 + tests/myapp_all/templates/page.html | 6 + tests/myapp_all/tests.py | 140 +++ tests/myapp_all/urls.py | 14 + tests/myapp_all/urls_news.py | 16 + tests/myapp_cms/__init__.py | 1 + tests/myapp_cms/admin.py | 35 + tests/myapp_cms/cms_app.py | 11 + tests/myapp_cms/cms_plugins.py | 13 + tests/myapp_cms/fixtures/tests_data.json | 394 ++++++++ tests/myapp_cms/models.py | 35 + tests/myapp_cms/templates/base.html | 13 + tests/myapp_cms/templates/list-cms.html | 1 + tests/myapp_cms/templates/page.html | 6 + tests/myapp_cms/tests.py | 150 +++ tests/myapp_cms/urls.py | 13 + tests/myapp_cms/urls_news.py | 16 + tests/myapp_hvad/__init__.py | 1 + tests/myapp_hvad/fixtures/tests_data.json | 856 ++++++++++++++++++ tests/myapp_hvad/models.py | 27 + tests/myapp_hvad/tests.py | 106 +++ tests/myapp_hvad/urls.py | 23 + tests/runtests.sh | 26 + tests/settings.py | 40 + tests/settings_all.py | 24 + tests/settings_cms.py | 53 ++ tests/settings_hvad.py | 18 + tests/utils.py | 256 ++++++ tox.ini | 77 ++ 81 files changed, 6365 insertions(+) create mode 100644 .gitignore create mode 100644 AUTHORS create mode 100644 LICENSE create mode 100644 MANIFEST.in create mode 100644 README.md create mode 100644 ROADMAP.md create mode 100644 TESTING.md create mode 100644 newsbox/__init__.py create mode 100644 newsbox/admin.py create mode 100644 newsbox/locale/fr/LC_MESSAGES/django.mo create mode 100644 newsbox/locale/fr/LC_MESSAGES/django.po create mode 100644 newsbox/migrations/__init__.py create mode 100644 newsbox/models.py create mode 100644 newsbox/templates/newsbox/detail.html create mode 100644 newsbox/templates/newsbox/list.html create mode 100644 newsbox/templatetags/__init__.py create mode 100644 newsbox/templatetags/get_placeholder_content.py create mode 100644 newsbox/urls.py create mode 100644 newsbox/utils.py create mode 100644 newsbox/views.py create mode 100644 newsbox_cms/__init__.py create mode 100644 newsbox_cms/admin.py create mode 100644 newsbox_cms/cms_plugins.py create mode 100644 newsbox_cms/locale/fr/LC_MESSAGES/django.mo create mode 100644 newsbox_cms/locale/fr/LC_MESSAGES/django.po create mode 100644 newsbox_cms/models.py create mode 100644 newsbox_cms/static/newsbox_cms/custom_model.css create mode 100644 newsbox_cms/templates/newsbox_cms/detail-cms.html create mode 100644 newsbox_cms/templates/newsbox_cms/list-cms.html create mode 100644 newsbox_hvad/__init__.py create mode 100644 newsbox_hvad/admin.py create mode 100644 newsbox_hvad/models.py create mode 100644 newsbox_hvad/urls.py create mode 100644 newsbox_hvad/views.py create mode 100755 setup.py create mode 100644 test_requirements/django-1.6.txt create mode 100644 test_requirements/django-1.6_cms-3.0.txt create mode 100644 test_requirements/requirements_base.txt create mode 100644 tests/myapp/README.md create mode 100644 tests/myapp/__init__.py create mode 100644 tests/myapp/admin.py create mode 100644 tests/myapp/fixtures/tests_data.json create mode 100644 tests/myapp/models.py create mode 100644 tests/myapp/tests.py create mode 100644 tests/myapp/urls.py create mode 100644 tests/myapp_all/__init__.py create mode 100644 tests/myapp_all/admin.py create mode 100644 tests/myapp_all/cms_app.py create mode 100644 tests/myapp_all/cms_plugins.py create mode 100644 tests/myapp_all/fixtures/tests_data.json create mode 100644 tests/myapp_all/models.py create mode 100644 tests/myapp_all/templates/base.html create mode 100644 tests/myapp_all/templates/list-cms.html create mode 100644 tests/myapp_all/templates/page.html create mode 100644 tests/myapp_all/tests.py create mode 100644 tests/myapp_all/urls.py create mode 100644 tests/myapp_all/urls_news.py create mode 100644 tests/myapp_cms/__init__.py create mode 100644 tests/myapp_cms/admin.py create mode 100644 tests/myapp_cms/cms_app.py create mode 100644 tests/myapp_cms/cms_plugins.py create mode 100644 tests/myapp_cms/fixtures/tests_data.json create mode 100644 tests/myapp_cms/models.py create mode 100644 tests/myapp_cms/templates/base.html create mode 100644 tests/myapp_cms/templates/list-cms.html create mode 100644 tests/myapp_cms/templates/page.html create mode 100644 tests/myapp_cms/tests.py create mode 100644 tests/myapp_cms/urls.py create mode 100644 tests/myapp_cms/urls_news.py create mode 100644 tests/myapp_hvad/__init__.py create mode 100644 tests/myapp_hvad/fixtures/tests_data.json create mode 100644 tests/myapp_hvad/models.py create mode 100644 tests/myapp_hvad/tests.py create mode 100644 tests/myapp_hvad/urls.py create mode 100755 tests/runtests.sh create mode 100644 tests/settings.py create mode 100644 tests/settings_all.py create mode 100644 tests/settings_cms.py create mode 100644 tests/settings_hvad.py create mode 100644 tests/utils.py create mode 100644 tox.ini diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5512008 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.pyc +django_newsbox.egg-info +*~ +.tox +tests/mydatabase diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..bf4584e --- /dev/null +++ b/AUTHORS @@ -0,0 +1,3 @@ +* Webu (webu.coop) https://github.com/webu +* Dylann CORDEL <d.cordel@webu.coop> https://github.com/dylannCordel +* Olivier Le Brouster <o.lebrouster@webu.coop> diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4c36e0a --- /dev/null +++ b/LICENSE @@ -0,0 +1,25 @@ +.===================================================================. +|| Copyright (c) 2013, Webu || +|| Currently under Beerware License || +|| ___ || +|| .' '. || +|| / \ oOoOo || +|| | | ,==||||| || +|| \ / _|| ||||| || +|| '.___.' _.-'^|| ||||| || +|| __/_______.-' '==HHHHH || +|| _.-'` / """"" || +|| .-' / oOoOo || +|| `-._ / ,==||||| || +|| '-/._|| ||||| || +|| / ^|| ||||| || +|| / '==HHHHH || +|| /________""""" || +|| `\ `\ || +|| \ `\ / || +|| \ `\/ || +|| / || +|| / || +|| jgs /_____ || +|| || +'===================================================================' diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..4d32fdf --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,12 @@ +include AUTHORS +include LICENSE +include MANIFEST.in +include README.md +include ROADMAP.md +include TESTING.md +recursive-include tests * +recursive-include test_requirements * +recursive-include newsbox/templates * +recursive-include newsbox/locale * +recursive-include newsbox_cms/templates * +recursive-include newsbox_cms/locale * diff --git a/README.md b/README.md new file mode 100644 index 0000000..2c11697 --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# Django News Box + +This django app is a toolbox to easily setup news in your projects. + +## Features + + * easy custom fields + * optional SEO fields + * optional publication period + * optional i18n support via hvad + * optional django-cms support + +## Installation + +## django CMS integration + +### models.py + + class News(NewsboxCMSBase, NewsboxSEOBase): + + class Meta: + newsbox_detail_url_name = "news_detail" # optional + +### cms_app.py + + class NewsApphook(CMSApp): + name = _("News") + urls = ["myproject.news_urls"] + + apphook_pool.register(NewsApphook) + + +### news_urls.py + + from django.conf.urls import patterns, url + from newsbox.views import NewsboxDetailView + from .models import News + + urlpatterns = patterns( + '', + url( + r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/(?P<slug>[0-9a-zA-Z_-]+)/$', + NewsboxDetailView.as_view( + template_name="myproject/news_detail.html", + model=News,), + name='news_detail'), + ) + +### cms_plugin.py + +TODO diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..53a7651 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,51 @@ +# Feuile de route du développement de l'application + +## Classes abstraites + +* [OK] News "basiques" +* [OK] News qui se périment dans le temps +* [OK] News optimisée pour le SEO +* [TODO] News avec auteur +* [TODO] : internationnaliser les contenus utiles (hvad ?) + +## Gestion des droits + +[TODO] + +## Tests unitaires + +[TODO] + +## Interface d'administration pour gérer les actualités + +* lien directe pour publier / dépublier une news +* [TODO] lien pour la gestion du multi langue comme pour les pages +* [TODO] à voir si c'est possible : lien d'affichage sur le site ? + +## Template basique pour afficher la liste des news + +TODO + +## Template basique pour afficher le détail d'une news + +TODO + +## Intégration à Django-CMS + +### Plugin pour ajouter les news sur les pages + +TODO + +### Édition / ajout front-end des news + +TODO + +## Intégration des catégories + +TODO ? Utile de l'intégrer plutot que de le laisser +à la discrétion de l'utilisateur ? + +## Questions : + +* liaison avec l'objet Site ? +* django-catégories ? à la discrétion de l'utilisateur ? diff --git a/TESTING.md b/TESTING.md new file mode 100644 index 0000000..d5e228b --- /dev/null +++ b/TESTING.md @@ -0,0 +1,25 @@ +Testing newsbox and newsbox_cms +================================= + +Testing in multiple environment +------------------------------- + +It's the better way to test this application. You will test it with many +versions of Python, Django and Django CMS for newsbox_cms. + +## Requirements + +First, you need to install tox:: + + pip install "tox>=1.6,<1.8" + + + +Testing in your specific environnement +-------------------------------------- + +If you don't care about tests this app in other environnements than yours, you +can only execute runtests.sh from "tests" directory. Newsbox will be tested +with your versions of python, Django, installed python modules etc. +It can be usefull if you run a very specific environnement which is not tested +with our tox configurations. diff --git a/newsbox/__init__.py b/newsbox/__init__.py new file mode 100644 index 0000000..1c06be7 --- /dev/null +++ b/newsbox/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +__version__="0.1.0" diff --git a/newsbox/admin.py b/newsbox/admin.py new file mode 100644 index 0000000..b76dc1f --- /dev/null +++ b/newsbox/admin.py @@ -0,0 +1,325 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +import copy + +from django.conf.urls import url, patterns +from django.contrib import messages, admin +from django.contrib.admin.models import LogEntry, CHANGE +from django.contrib.admin.templatetags.admin_static import static +from django.contrib.contenttypes.models import ContentType +from django.core.urlresolvers import reverse +from django.http import HttpResponseForbidden, HttpResponseRedirect +from django.shortcuts import get_object_or_404 +from django.utils.translation import ugettext_lazy as _, ungettext_lazy +from django.utils import six + + +def get_fieldset_by_field(name, fieldsets): + """ + Return fieldset containing a field given by name + """ + for fieldset in fieldsets: + options = fieldset[1] + if name in options.get('fields', {}): + return fieldset + return None + + +def remove_field_from_fieldsets(name, fieldsets, remove_empty_fieldset=True): + """ + Remove a field from all fieldset in fieldsets. + """ + while True: + fieldset = get_fieldset_by_field(name, fieldsets) + if fieldset: + fieldset[1]['fields'].remove(name) + if remove_empty_fieldset and len(fieldset[1]['fields']) == 0: + fieldsets.remove(fieldset) + else: + break + + +def add_fields_to_fieldset( + fields, + fieldsets, + after_field=None, + same_fieldset_as=None, + default_fieldset_name=None, + default_fieldset_classes=None, + default_fieldset_position=None, + replace_existing_field=False, + remove_empty_fieldset=False, +): + """ + Add fields in a fieldsets attribute + + Try to find a fieldset containing same_fieldset_as value in fields. If not + found a new fieldset is created with name `default_fieldset_name`, position + `default_fieldset_position` and classes `default_fieldset_classes`. + + Fields are inserted just after after_field. If not found, they are inserted + at the end. + + If replace_existing_field is True, existing fields in fieldsets with same + name are removed. + + """ + if same_fieldset_as is None and after_field: + same_fieldset_as = after_field + + # Find fieldset + fieldset = get_fieldset_by_field(same_fieldset_as, fieldsets) + + if fieldset is None: + fieldset = (default_fieldset_name, { + 'fields': [], + 'classes': default_fieldset_classes, + }) + allready_inserted = False + else: + allready_inserted = True + + # Insert fields + index = None + if after_field: + index = fieldset[1]['fields'].index(after_field) + 1 + + index = index or len(fieldset[1]['fields']) + for field in fields: + if replace_existing_field: + remove_field_from_fieldsets( + field, fieldsets, + remove_empty_fieldset=remove_empty_fieldset) + elif get_fieldset_by_field(field, fieldsets) is not None: + continue + + fieldset[1]['fields'].insert(index, field) + index += 1 + + # Insert fieldset if needed. + if not allready_inserted and len(fieldset[1]['fields']) > 0: + if default_fieldset_position is not None: + fieldsets.insert(default_fieldset_position, fieldset) + else: + fieldsets.append(fieldset) + + +def changestatus_link(obj): + if obj.newsbox_published: + title = _('Unpublish this %s') % six.text_type( + obj._meta.verbose_name) + icon_url = static('admin/img/icon-yes.gif') + else: + title = _('Publish this %s') % six.text_type( + obj._meta.verbose_name) + icon_url = static('admin/img/icon-no.gif') + return '<a href="%s" title="%s"><img src="%s" alt="%s" /></a>' % ( + reverse('admin:admin_newsbox_%s_change_status' % ( + six.text_type(obj._meta.verbose_name)), + args=[obj.pk, ]), + title, icon_url, obj.newsbox_published) + + +changestatus_link.allow_tags = True +changestatus_link.admin_order_field = 'newsbox_published' +changestatus_link.short_description = _('published') + + +class NewsboxBaseAdmin(admin.ModelAdmin): + + list_filter = ('newsbox_publication_start_date', 'newsbox_published', ) + list_display = ['get_newsbox_title', 'newsbox_date', + 'get_newsbox_slug', changestatus_link] + list_display_links = ('get_newsbox_title',) + fieldsets = [ + (None, { + 'fields': ['newsbox_title', 'newsbox_slug', 'newsbox_date', 'newsbox_published', ], }), + (_('Content'), { + 'fields': ['newsbox_summary', 'newsbox_body'], }), ] + actions = ['publish', 'unpublish'] + save_as = True + + def __init__(self, *args, **kwargs): + # This is a workaround for prepopulated_fields with hvad + self.prepopulated_fields = {"newsbox_slug": ("newsbox_title",)} + super(NewsboxBaseAdmin, self).__init__(*args, **kwargs) + + def get_fieldsets(self, request, obj=None): + """ + Prevent anoying modification of fieldsets class attribute. + """ + fieldsets = super(NewsboxBaseAdmin, self).get_fieldsets(request, obj) + return copy.deepcopy(fieldsets) + + def get_newsbox_title(self, obj): + return obj.newsbox_title + get_newsbox_title.short_description = _('Title') + + def get_newsbox_slug(self, obj): + return obj.newsbox_slug + get_newsbox_slug.short_description = _('Slug') + + def get_urls(self): + urls = super(NewsboxBaseAdmin, self).get_urls() + my_urls = patterns('', url( + r'^([0-9]+)/change-status/$', + self.admin_site.admin_view(self.change_status), + name='admin_newsbox_%s_change_status' % ( + six.text_type(self.model._meta.verbose_name),))) + return my_urls + urls + + def change_status(self, request, news_id): + """ + Switch the status of a news + """ + + news = get_object_or_404(self.model, pk=news_id) + if not news.has_publish_permission(request): + return HttpResponseForbidden( + _('You do not have permission to publish this %s') + % (six.text_type(self.model._meta.verbose_name),)) + + news.newsbox_published = not news.newsbox_published + news.save() + if news.newsbox_published: + messages.info( + request, + _( + 'The %(objtype)s "%(objtitle)s" was ' + 'successfully published' + ) % { + 'objtype': six.text_type(self.model._meta.verbose_name), + 'objtitle': news} + ) + else: + messages.info( + request, + _( + 'The %(objtype)s "%(objtitle)s" was ' + 'successfully unpublished' + ) % { + 'objtype': six.text_type(self.model._meta.verbose_name), + 'objtitle': news} + ) + LogEntry.objects.log_action( + user_id=request.user.id, + content_type_id=ContentType.objects.get_for_model(self.model).pk, + object_id=news_id, + object_repr=six.text_type(news), + action_flag=CHANGE, + ) + return HttpResponseRedirect('../../') + + def publish(self, request, queryset): + """ + Marks selected news items as published + """ + ok = 0 + for news in queryset: + if news.newsbox_published: + continue + + if not news.has_publish_permission(request): + messages.error( + request, + _( + 'You do not have permission to publish the ' + '%(objtype)s "%(objtitle)s"' + ) % { + 'objtype': six.text_type(self.model._meta.verbose_name), + 'objtitle': news + } + ) + continue + news.newsbox_published = True + news.save() + ok += 1 + + messages.success(request, ungettext_lazy( + '%(nb)d %(objtype)s was published', + '%(nb)d %(objtype)s were published', + ok) % {'nb': ok, 'objtype': self.model._meta.verbose_name}) + publish.short_description = _('Publish selected %(verbose_name_plural)s') + + def unpublish(self, request, queryset): + """ + Marks selected news items as unpublished + """ + ok = 0 + for news in queryset: + if not news.newsbox_published: + continue + + if not news.has_publish_permission(request): + messages.error( + request, + _( + 'You do not have permission to unpublish the ' + '%(objtype)s "%(objtitle)s"' + ) % { + 'objtype': six.text_type(self.model._meta.verbose_name), + 'objtitle': news + } + ) + continue + news.newsbox_published = False + news.save() + ok += 1 + + messages.success(request, ungettext_lazy( + '%(nb)d %(objtype)s was unpublished', + '%(nb)d %(objtype)s were unpublished', + ok) % { + 'nb': ok, + 'objtype': self.model._meta.verbose_name, + } + ) + unpublish.short_description = _( + 'Unpublish selected %(verbose_name_plural)s') + +class NewsboxAdmin(NewsboxBaseAdmin): + pass + + +class NewsboxExpiredAdmin(NewsboxBaseAdmin): + + def get_fieldsets(self, request, obj=None): + fieldsets = super(NewsboxExpiredAdmin, self).get_fieldsets(request, obj) + + remove_field_from_fieldsets('newsbox_published', fieldsets) + add_fields_to_fieldset( + ['newsbox_published', + 'newsbox_publication_start_date', + 'newsbox_publication_end_date', ], + fieldsets, + default_fieldset_name=_('Publication'), + default_fieldset_position=1) + + return fieldsets + + def get_list_display(self, request): + list_display = super(NewsboxExpiredAdmin, self).get_list_display(request) + + list_display = list_display[:2] +\ + ['newsbox_publication_end_date',] + list_display[2:] + return list_display + +class NewsboxSEOAdmin(NewsboxBaseAdmin): + + def get_fieldsets(self, request, obj=None): + fieldsets = super(NewsboxSEOAdmin, self).get_fieldsets(request, obj) + + add_fields_to_fieldset( + ['newsbox_indexed', + 'newsbox_meta_description', + 'newsbox_meta_keywords', ], + fieldsets, + default_fieldset_name=_('SEO Settings'), + default_fieldset_classes=('collapse',), + ) + + return fieldsets + + def get_list_display(self, request): + list_display = super(NewsboxSEOAdmin, self).get_list_display(request) + return list_display diff --git a/newsbox/locale/fr/LC_MESSAGES/django.mo b/newsbox/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..568c03c52430e6f7dc02de3913e9bac2a42b084f GIT binary patch literal 4568 zcmcJRO>87b6@V+S1Y!tD7Lq{tNntRycQdmy%Mv!TKg6-Ui^Z&M?D6s=!O}Bb<7ua- zd$z0E-pLI`h!Y0{5f_lSC4++C0D=n_MnaL`!UYKl!G%k1AVd%n5`3?_$1^tedUK%V zp3mJ~_3HiAd-bQ&r(RNApWyx=_fPLr>N>2yl^?FoDW#r+0lWrZg%{!9;oIR;Z&T_a zcmci#F2M)j7vMW#6TTNl#rqfGyLtX5ybQkwW!*o(2jLq~=AF7<sX6#C6#36Uk-Gxl z1vd+R6{3pj!WvBACHNzF7QPNk@KKaSv|5B3uD~;J2R;H{f;ZsH@B;h?T!Lrbk<X9e zHJ-l@Wxc;Z(f9S@`JV;<4VkL$L)nMn0|lReGX5--`OiS{%T@Ro+=Tq89e(7ygCeI7 zMenacvHKhFHZl4R+~N6toF%*sH{c(k%sa<mk^3q5QMd|E!vu=GUxy!p--VCDpFxS= zZ{RKX=i>XPQTqKne;FcL?Lo<v7ophqbI6~1jh`pr@8JjF-=Ns>Ai=&0Ps0WHIVk@9 zHk^g8L9y?zP{TLi)9`VEF8Zv(2sYtY;P2oHtgv_$z5wg+RVZ@)1;xJqKw1A09teqg z4B|5NB>XU(hy1C}@WW8`B{&72hhoPr6#sk+%KRTgk@t(@`Ik`E`!y85{1y_HEZ4+- ziLG1`i!!&!#-*7}=b>D(#UAGtKa4KXQQ}0}s`=t2E>RyZ{uiC(dP|N2znUk}RW7kX z;{OzPmHQmG#96LNj?8}1eUAHM#XH=a*?9(@<rd#eb4w15F4?bg&2UTXB_G5WPjbs8 z`6534h&*t;Pkv_RqUOA>XXfJOj_dc#yw!W2)xESC2DW4TBL|qooG=0rX>_uX$uSEN zQ-a7hcZ{zivxg!<80si?x@q+2L$j}~@sd_Yn`k?Tj4i9hIC3U(YALY2(CceY_q=VB z>_5kC?TH{ns#TGTWiJ0O`qfYLOz~E%*Dlt6E`|YjTrnx_Hcg_Dlgl{pI5DNHrz_L4 zR=lVCaXRruFVyS#<aJcT+fgP1XU7pwE_PlxZ`FEYc7r&z#ZZYs%X2{-sr5V_*dCge z!$C81yC!MI*4&D`uDR6<(<B#B40N5qifJ3h^K~~)jM`jY)0@V*AlkNS)0nYSHp6sV zH9Df#I18rphros8#B`Pv+NQ0Rv9_ItVSge4?qTYInUhhMxvfr&AyH<vJ`@Ix89}t` zg@K=`*z*!6k#Nj&q8$HuPDZ5`w**o4Wox6Z8uB&&os2}&wDCqZD$9edQJS9Y+wstm zcR$}jZBZr5SKEox(AV2B8MbT6deeE1V0KfRrSNnSMB`6ubSTV?_s6STTCB~TUQnng za?5q&?HX;mJ=YgYB17nlL1pzt63yo&+oU7IdM4=x){-<bw%CH1j>kv$o`vK&b@wIr zqkGb#&Dig&R${UY*S_bB%6^O=I92R-6?!-??a7CHNY^+|`^L7CpqFip?8Wn@zZWOI zRoM>Btj>21Wx~%VPQJ8G(kNT4@DP>G$~LfRx9cT+mF1Rli5J;0Q&4tiyu;=zt@x#z zCJ_(U^!mc$XBVz7>zm6Pn=5OpQyZoiC$4nEZU=tpxpdo>8gWfet*<poi-o17C2Xnb z^Ofp_Ql(m|Uewi3*3LhDwo<KB7+Bh%28i&xj;rIAQlro=PHK9oA9_)w7jc3K_2pK^ zvj1#5F{a#3u1?jxXgj6&lp4nC)^vSg_4<}*ez{(MHVn#fvOOMy#y3`OERW5smMc?5 znJqP_lQr$Aj^`-1L3D}z>m}B>D_f0grHkWnqFvi0rRAs<`&6BpzSs=h)OuE`O4s6~ zYil~nE0?`;{*uoBy)qZ+tGYUWX-XZ@oIE`oxZyzi!$B6g;ebN6Yg$=t8opwWnnQp1 z-&yv=Y5%XKwjxw+xs;kFmPG7SvVAzXBew9(n#9vPUf0V?-{=E{PltwT5<8P7mMx$Y z)9M&np($EmsutSqfM*&hg}|dfW~p1emd?X07pD$6B5SOLRdt#o-)G0~)WU?4d83rr z9~h&DKhR#jXfiS05{_Wkqc783<8G5`c0lqG?<OVXjZ`X`VVBO17SN5gt;X`^Vb%4V zCDSJComYputW6V|+o;Ws?P69k9JGc5p92KCt{-l>6k2iAG2K?%;XwK^yEP(s#eC+p z=(Ds_@hYZ=p16bZww6__Ja)rDdpJl;)G}Q;yxfd~<hame{dqALd3=W+rR&k#;-04; zyRqt|&fUT<ZJffT4F$XC*hbamFqXK0_;Vf#9NtJ>K;xBM_a$uMY|*SaqR_G#Fp*O1 zQIbd;D81UKrDE5=$*@dJ+mDP?VOc8lZl@;X91%{We!d5#4mU#@Ii}MwTuL&=0k!0Z zqULnr=xN=HNiU=v5+OrJBGlcN8|`{3pxvLN>r?=W0Wa9L#UitruF-69M##%Vne>rU z<1Cf%1ssl7@%#87Ak!tY$C-I-8og;r_T(9(l)9JYX<R+4q%%vcYOy=>5+-j{mp;<Q z3OOC*^>TltZ;~h&zCv8`LB+YbOSd?5T*%%~MXhdy!+}*31#h%$n`7k2XN92AC)RCB g9uyuezK-@>euhA4juFFw93seS4iSEu6$z{U3q-as%K!iX literal 0 HcmV?d00001 diff --git a/newsbox/locale/fr/LC_MESSAGES/django.po b/newsbox/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..ec7afe0 --- /dev/null +++ b/newsbox/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,270 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-01-18 15:31+0100\n" +"PO-Revision-Date: 2014-01-18 15:26+0100\n" +"Last-Translator: Dylann Cordel <cordel.d@free.fr>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: admin.py:28 +msgid "translations" +msgstr "traductions" + +#: admin.py:53 +msgid "edit" +msgstr "modifier" + +#: admin.py:56 models.py:72 +msgid "title" +msgstr "titre" + +#: admin.py:61 +#, python-format +msgid "Unpublish this %s" +msgstr "Dépublier cette %s" + +#: admin.py:65 +#, python-format +msgid "Publish this %s" +msgstr "Publier cette %s" + +#: admin.py:75 models.py:169 +msgid "published" +msgstr "publiée" + +#: admin.py:86 +msgid "Content" +msgstr "Contenu" + +#: admin.py:100 newsboxcms/models.py:14 +msgid "Title" +msgstr "Titre" + +#: admin.py:104 +msgid "Slug" +msgstr "Slug" + +#: admin.py:123 +#, python-format +msgid "You do not have permission to publish this %s" +msgstr "Vous n'avez pas la permission de publier cette %s" + +#: admin.py:129 +#, python-format +msgid "The %(objtype)s \"%(objtitle)s\" was successfully published" +msgstr "Cette %(objtype)s \"%(objtitle)s\" a été publiée avec succès" + +#: admin.py:135 +#, python-format +msgid "The %(objtype)s \"%(objtitle)s\" was successfully unpublished" +msgstr "Cette %(objtype)s \"%(objtitle)s\" a été dépubliée avec succès" + +#: admin.py:160 +#, python-format +msgid "You do not have permission to publish the %(objtype)s \"%(objtitle)s\"" +msgstr "" +"Vous n'avez pas la permission de publier cette %(objtype)s \"%(objtitle)s\"" + +#: admin.py:172 +#, python-format +msgid "%(nb)d %(objtype)s was published" +msgid_plural "%(nb)d %(objtype)s were published" +msgstr[0] "%(nb)d %(objtype)s a été dépubliée avec succès" +msgstr[1] "%(nb)d %(objtype)s ont été dépubliées avec succès" + +#: admin.py:175 +#, python-format +msgid "Publish selected %(verbose_name_plural)s" +msgstr "Publier les %(verbose_name_plural)s sélectionnées" + +#: admin.py:188 +#, python-format +msgid "" +"You do not have permission to unpublish the %(objtype)s \"%(objtitle)s\"" +msgstr "" +"Vous n'avez pas la permission de dépublier cette %(objtype)s \"%(objtitle)s\"" + +#: admin.py:200 +#, python-format +msgid "%(nb)d %(objtype)s was unpublished" +msgid_plural "%(nb)d %(objtype)s were unpublished" +msgstr[0] "%(nb)d %(objtype)s a été dépubliée avec succès" +msgstr[1] "%(nb)d %(objtype)s ont été dépubliées avec succès" + +#: admin.py:208 +#, python-format +msgid "Unpublish selected %(verbose_name_plural)s" +msgstr "Dépublier les %(verbose_name_plural)s sélectionnées" + +#: admin.py:237 +msgid "Publication" +msgstr "Publication" + +#: admin.py:244 +msgid "SEO Settings" +msgstr "Options de référencement" + +#: models.py:75 +msgid "slug" +msgstr "slug" + +#: models.py:77 +msgid "The part of the title that is used in the URL" +msgstr "La partie du titre utilisée dans l'URL" + +#: models.py:85 models.py:95 +msgid "summary" +msgstr "résumé" + +#: models.py:89 models.py:97 +msgid "body" +msgstr "corps" + +#: models.py:104 +msgid "meta description" +msgstr "méta description" + +#: models.py:107 +msgid "meta keywords" +msgstr "méta mots clés" + +#: models.py:147 +msgid "creation date" +msgstr "date de création" + +#: models.py:151 +msgid "last update date" +msgstr "date de dernière modification" + +#: models.py:157 +msgid "date" +msgstr "date" + +#: models.py:162 +msgid "publication start date" +msgstr "date de début de publication" + +#: models.py:165 +msgid "" +"When the news should go live. Status must be \"Published\" for news to go " +"live." +msgstr "" +"Date à laquelle l'actualité sera visible. Le statut doit être \"publié\" " +"pour que l'actualité soit visible." + +#: models.py:178 +#, python-format +msgid "News n° %s" +msgstr "Actualité n° %s" + +#: models.py:236 models.py:237 +msgid "news" +msgstr "actualité" + +#: models.py:252 +msgid "publication end date" +msgstr "date de fin de publication" + +#: models.py:255 +msgid "When to expire the news.Leave empty to never expire." +msgstr "" +"Date à laquelle l'actualité ne sera plus visible. Laisser vide pour qu'elle " +"n'expire jamais." + +#: models.py:269 +msgid "indexed" +msgstr "indéxée" + +#: models.py:272 +msgid "An unindexed news will not be indexed by search engines." +msgstr "" +"Une actualité non indéxée ne sera jamais indéxée par les moteurs de recherche" + +#: views.py:21 newsboxcms/cms_plugins.py:21 +msgid "The choosen news type to display is invalid" +msgstr "Le type d'actualité à afficher choisi est invalide" + +#: newsboxcms/cms_plugins.py:10 +msgid "News list" +msgstr "Liste d'actualité" + +#: newsboxcms/models.py:11 +msgid "News type to display" +msgstr "Type d'actualité à afficher" + +#: newsboxcms/models.py:16 +msgid "Title to display before the list" +msgstr "Titre à afficher avant la liste" + +#: newsboxcms/models.py:18 +msgid "Number of news" +msgstr "Nombre d'actualité" + +#: newsboxcms/models.py:20 +msgid "Number of news to display. \"0\" allow you to display ALL news" +msgstr "" +"Nombre d'actualité à afficher. \"0\" permet d'afficher TOUTES les actualités " +"(sans pagination)" + +#: newsboxcms/models.py:23 +msgid "Display a pager" +msgstr "Affiche une pagination" + +#: newsboxcms/models.py:29 +#, fuzzy, python-format +msgid "Display of a news" +msgid_plural "Display of %(nb)d news" +msgstr[0] "Affichage de toutes les actualités" +msgstr[1] "Affichage de toutes les actualités" + +#: newsboxcms/models.py:33 +msgid "Display of all news" +msgstr "Affichage de toutes les actualités" + +#: newsboxcms/templates/newsboxcms/list-cms.html:11 +#: templates/newsbox/list.html:38 +msgid "Read more" +msgstr "Lire la suite" + +#: templates/newsbox/list.html:53 +msgid "Previous news" +msgstr "Actualités précédentes" + +#: templates/newsbox/list.html:57 +#, python-format +msgid "Page %(number)s on %(total)s" +msgstr "Page %(number)s sur %(total)s" + +#: templates/newsbox/list.html:61 +msgid "Next news" +msgstr "Actualités suivantes" + +#: templates/newsbox/list.html:65 +msgid "See all news" +msgstr "Voir toutes les actualités" + +#~ msgid "" +#~ "\n" +#~ " Page %(number)s on %(total)s\n" +#~ " " +#~ msgstr "" +#~ "\n" +#~ " Page %(number)s sur %(total)s\n" +#~ " " + +#, fuzzy +#~ msgid "%d %s was published" +#~ msgid_plural "%d %s were published" +#~ msgstr[0] "publiée" +#~ msgstr[1] "publiée" diff --git a/newsbox/migrations/__init__.py b/newsbox/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/newsbox/models.py b/newsbox/models.py new file mode 100644 index 0000000..10ef5d1 --- /dev/null +++ b/newsbox/models.py @@ -0,0 +1,268 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +import sys +from datetime import datetime + +from django.core.urlresolvers import reverse +from django.db import models +from django.utils.timezone import utc +from django.utils.translation import ugettext_lazy as _ +from django.utils.encoding import python_2_unicode_compatible +from django.utils import six + +newsbox_models = [] + +def newsbox_mcls_processor(mcls, class_name, class_bases, class_attrs, base, newsbox_opts): + class_attrs['newsbox_title'] = models.CharField( + verbose_name=_('title'), + max_length=255) + class_attrs['newsbox_slug'] = models.SlugField( + verbose_name=_('slug'), + unique_for_date='newsbox_date', + help_text=_('The part of the title that is used in the URL')) + class_attrs['newsbox_summary'] = models.TextField( + verbose_name=_('summary')) + class_attrs['newsbox_body'] = models.TextField( + verbose_name=_('body'), + null=False, blank=True) + newsbox_opts['trans_fieldnames']+=[ + 'newsbox_title', 'newsbox_slug', + 'newsbox_summary', 'newsbox_body'] + +def newsboxseo_mcls_processor(mcls, class_name, class_bases, class_attrs, base, newsbox_opts): + class_attrs['newsbox_meta_description'] = models.TextField( + verbose_name=_('meta description'), + max_length=255, blank=True, null=True) + class_attrs['newsbox_meta_keywords'] = models.CharField( + verbose_name=_('meta keywords'), + max_length=255, blank=True, null=True) + + newsbox_opts['trans_fieldnames']+=[ + 'newsbox_meta_description', 'newsbox_meta_keywords'] + +class NewsboxManager(models.Manager): + """ + Filter published news + """ + + def published(self): + now = datetime.utcnow().replace(tzinfo=utc) + query_set = super(NewsboxManager, self).get_query_set().filter( + # Only published News + models.Q(newsbox_published=True), + ).exclude( + # exclude news with publication start date in the future + models.Q(newsbox_publication_start_date__gt=now) + ) + + if issubclass(self.model, NewsboxExpiredBase): + query_set = query_set.exclude( + # exclude news which are obsolete + models.Q(newsbox_publication_end_date__lte=now) + ) + return query_set + + +class NewsboxModelBase(models.base.ModelBase): + """ + Metaclass used to inject django-newsboxfunctionalities into django + orm. + """ + + def __new__(mcls, class_name, class_bases, class_attrs): + super_new = super(NewsboxModelBase, mcls).__new__ + + # six.with_metaclass() inserts an extra class called 'NewBase' in the + # inheritance tree: Model -> NewBase -> object. But the initialization + # should be executed only once for a given model class. + + # attrs will never be empty for classes declared in the standard way + # (ie. with the `class` keyword). This is quite robust. + if class_name == 'NewBase' and class_attrs == {}: + return super_new(mcls, class_name, class_bases, class_attrs) + + # Also ensure initialization is only performed for subclasses of Model + # (excluding Model class itself). + parents = [b for b in class_bases if isinstance(b, NewsboxModelBase) and + not (b.__name__ == 'NewBase' and b.__mro__ == (b, object))] + if not parents: + return super_new(mcls, class_name, class_bases, class_attrs) + + #retrieve newsbox options in Meta class and delete these from the + #Meta class to avoid django complain about unsupported keys. + #We register our meta options in `_newsbox_meta` + attr_meta = class_attrs.get('Meta', None) + if attr_meta and not getattr(attr_meta, 'ordering', None): + class_attrs['Meta'].ordering = ('-newsbox_date',) + abstract = getattr(attr_meta, 'abstract', False) + newsbox_opts = {} + newsbox_opts_keys = [ + 'detail_url_name', + 'metaclass_base_processor', + 'metaclass_final_processor', + 'trans_fieldnames'] + for opt in newsbox_opts_keys: + newsbox_opt = 'newsbox_' + opt + if hasattr(attr_meta, newsbox_opt): + newsbox_opts[opt] = getattr(attr_meta, newsbox_opt) + delattr(attr_meta, newsbox_opt) + + if 'trans_fieldnames' not in newsbox_opts: + newsbox_opts['trans_fieldnames'] = [] + + # register newsbox_objects manager + class_attrs['newsbox_objects'] = NewsboxManager() + + #Call specific metaclass processor of all bases + if not abstract : + for base in class_bases: + try: + processor = base._newsbox_meta['metaclass_base_processor'] + except (AttributeError, KeyError): + continue + processor = getattr(sys.modules[base.__module__], processor) + processor(mcls, class_name, class_bases, class_attrs, base, newsbox_opts) + + for base in class_bases: + try: + processor = base._newsbox_meta['metaclass_final_processor'] + except (AttributeError, KeyError): + continue + processor = getattr(sys.modules[base.__module__], processor) + processor(mcls, class_name, class_bases, class_attrs, base, newsbox_opts) + + if not 'default_manager' in class_attrs: + class_attrs['default_manager'] = class_attrs['newsbox_objects'] + if not 'objects' in class_attrs: + class_attrs['objects'] = class_attrs['newsbox_objects'] + + # contructs class + cls = super_new(mcls, class_name, class_bases, class_attrs) + + #Add the detail_url_name to _newsbox_meta. if not defined, we build the + #default one with this format : <app_label>_<model_name>_detail + #Names ar lowered. + if not abstract: + detail_url_name = newsbox_opts.get( + 'detail_url_name', + "%s_%s_detail" % (cls._meta.app_label.lower(), + cls._meta.model_name.lower(),) + ) + + newsbox_opts.update( + detail_url_name=detail_url_name, + ) + newsbox_models.append(cls) + cls.add_to_class('_newsbox_meta', newsbox_opts) + return cls + + +@python_2_unicode_compatible +class NewsboxBase(six.with_metaclass(NewsboxModelBase, models.Model)): + """ + Abstract class to build your own news + """ + + # Automatic fields + newsbox_creation_date = models.DateTimeField( + verbose_name=_('creation date'), + auto_now_add=True, + editable=False) + newsbox_changed_date = models.DateTimeField( + verbose_name=_('last update date'), + auto_now=True, + editable=False) + + # Basic Publication Fields + newsbox_date = models.DateTimeField( + verbose_name=_('date'), + default=datetime.now, db_index=True, + ) + + newsbox_publication_start_date = models.DateTimeField( + verbose_name=_('publication start date'), + default=datetime.now, db_index=True, + help_text=_( + 'When the news should go live. ' + 'Status must be "Published" for news to go live.')) + + newsbox_published = models.BooleanField( + verbose_name=_('published'), + blank=True, + default=True,) + + default_manager = NewsboxManager() + objects = default_manager + + def __str__(self): + return six.text_type(self.newsbox_title) + + def has_publish_permission(self, request): + if request.user.is_superuser: + return True + return request.user.has_perm('newsbox.publish_news', self) + + def has_change_permission(self, request): + if request.user.is_superuser: + return True + return request.user.has_perm('newsbox.change_news', self) + + def is_published(self): + if not self.newsbox_published: + return False + + if isinstance(self, NewsboxExpiredBase): + now = datetime.utcnow().replace(tzinfo=utc) + if now < self.newsbox_publication_start_date: + return False + if now > self.newsbox_publication_end_date: + return False + + return True + + def get_slug(self, *args, **kwargs): + return self.newsbox_slug + + def get_absolute_url(self, *args, **kwargs): + return reverse(self._newsbox_meta['detail_url_name'], args=( + self.newsbox_date.strftime("%Y"), + self.newsbox_date.strftime("%m"), + self.newsbox_date.strftime("%d"), + self.get_slug(),)) + + class Meta: + abstract = True + verbose_name = _('news') + verbose_name_plural = _('news') + ordering = ('-newsbox_date',) + newsbox_metaclass_base_processor = 'newsbox_mcls_processor' + +class NewsboxExpiredBase(six.with_metaclass(NewsboxModelBase, models.Model)): + """ + Define News which expires in time and will not be displayed in front + """ + newsbox_publication_end_date = models.DateTimeField( + verbose_name=_('publication end date'), + null=True, blank=True, db_index=True, + help_text=_( + 'When to expire the news.' + 'Leave empty to never expire.')) + + class Meta: + abstract = True + +class NewsboxSEOBase(six.with_metaclass(NewsboxModelBase, models.Model)): + """ + Define News which have SEO fields + """ + + # SEO Fields + newsbox_indexed = models.BooleanField( + verbose_name=_('indexed'), + default=True, + help_text=_( + 'An unindexed news will not be indexed by search engines.')) + + class Meta: + abstract = True + newsbox_metaclass_base_processor = 'newsboxseo_mcls_processor' diff --git a/newsbox/templates/newsbox/detail.html b/newsbox/templates/newsbox/detail.html new file mode 100644 index 0000000..09f53f3 --- /dev/null +++ b/newsbox/templates/newsbox/detail.html @@ -0,0 +1,22 @@ +{% load i18n %} + +<article class="newsbox_detail"> + {% block newsbox_detail_header %} + <header> + <h1>{{ news.newsbox_title }}</h1> + <time datetime="{{ news.newsbox_date }}">{{ news.newsbox_date|date:'d M. Y' }}</time> + </header> + {% endblock %} + + + {% block newsbox_detail_item_content %} + <div class="content"> + + {% if news.newsbox_body %} + {{ news.newsbox_body|linebreaks }} + {% else %} + {{ news.newsbox_summary|linebreaks }} + {% endif %} + </div> + {% endblock %} +</article> diff --git a/newsbox/templates/newsbox/list.html b/newsbox/templates/newsbox/list.html new file mode 100644 index 0000000..e3d263e --- /dev/null +++ b/newsbox/templates/newsbox/list.html @@ -0,0 +1,74 @@ +{% if news|length > 0 %} + {% load i18n %} + <section class="newsbox_plugin"> + + {% block newsbox_list_header %} + {% if title %} + <h1> + {% if title_url %} + <a href="{{ title_url }}">{{ title }}</a> + {% else %} + {{ title }} + {% endif %} + </h1> + {% endif %} + {% endblock %} + + + {% block newsbox_list %} + <div class="list"> + + {% for news in newsset %} + {% block newsbox_list_item %} + <div class="news"> + <header> + {% block newsbox_list_item_header %} + {% with news.get_absolute_url as url %} + <h2><a href="{{ url }}">{{ news.newsbox_title }}</a></h2> + {% endwith %} + <time datetime="{{ news.newsbox_date }}">{{ news.newsbox_date|date:'d M. Y' }}</time> + {% endblock %} + </header> + + {% block newsbox_list_item_content %} + <div class="summary"> + {{ news.newsbox_summary|linebreaks }} + {% if news.newsbox_body %} + <p class="readmore"><a href="{{ news.get_absolute_url }}"> + {% trans "Read more" %} + </a></p> + {% endif %} + </div> + {% endblock %} + + </div> + {% endblock %} + {% endfor %} + + + {% block newsbox_pager %} + {% if with_pager %} + <div class="pager"> + {% if newsset.has_previous %} + <a class="prev" href="?page={{ newsset.previous_page_number }}">{% trans "Previous news" %}</a> + {% endif %} + + <span class="current"> + {% blocktrans with newsset.number as number and newsset.paginator.num_pages as total %}Page {{ number }} on {{ total }}{% endblocktrans %} + </span> + + {% if newsset.has_next %} + <a class="next" href="?page={{ newsset.next_page_number }}">{% trans "Next news" %}</a> + {% endif %} + </div> + {% elif all_news_url %} + <a class="readmore" href="{{ all_news_url }}">{% trans "See all news" %}</a></p> + {% endif %} + {% endblock %} + + </div> + {% endblock %} + </section> +{% else %} + {% block newsbox_no_news %}{% endblock %} +{% endif %} diff --git a/newsbox/templatetags/__init__.py b/newsbox/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/newsbox/templatetags/get_placeholder_content.py b/newsbox/templatetags/get_placeholder_content.py new file mode 100644 index 0000000..f649636 --- /dev/null +++ b/newsbox/templatetags/get_placeholder_content.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django import template +from django.utils.safestring import mark_safe +from classytags.arguments import Argument +from classytags.core import Options +from cms.templatetags.cms_tags import RenderPlaceholder + + +register = template.Library() + + +class GetPlaceholderContent(RenderPlaceholder): + """ + With this tag, you can retrieve a placeholder's content into a variable + + Exemple : + {% get_placeholder_content news.newsbox_body as body %} + {% if body %} + {{ body|safe }} + some extra html + {% else %} + fall back + {% endif %} + {% endget_placeholder_content %} + """ + name = 'get_placeholder_content' + options = Options( + Argument('placeholder', resolve=True), + Argument('width', default=None, required=False), + 'language', + Argument('language', default=None, required=False), + 'as', + Argument('varname', resolve=False), + blocks=[ + ('endget_placeholder_content', 'nodelist'), + ] + ) + + def render_tag(self, context, placeholder, width, varname, language=None, nodelist=None): + placeholder_output = None + if placeholder: + placeholder_output = super(GetPlaceholderContent, self).render_tag( + context, placeholder, width, language) + + context.push() + context[varname] = mark_safe(placeholder_output) + output = nodelist.render(context) + context.pop() + return output + + +register.tag(GetPlaceholderContent) diff --git a/newsbox/urls.py b/newsbox/urls.py new file mode 100644 index 0000000..b0164b0 --- /dev/null +++ b/newsbox/urls.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.utils.text import slugify +from django.conf.urls import patterns, url, include +from django.conf.urls.i18n import i18n_patterns + +from .models import newsbox_models +from .views import NewsboxArchiveView, NewsboxYearArchiveView, \ + NewsboxMonthArchiveView, NewsboxDayArchiveView, NewsboxDetailView + +def get_urls( + archive_view=NewsboxArchiveView, + year_archive_view=NewsboxYearArchiveView, + month_archive_view=NewsboxMonthArchiveView, + day_archive_view=NewsboxDayArchiveView, + detail_view=NewsboxDetailView): + + urls = ['',] + for model in newsbox_models : + app_name = model._meta.app_label.lower() + model_name = model.__name__.lower() + + viewurl = 'newsbox/%s/%s/'\ + % (app_name, model_name,) + urls.append( + url( + r'^%s$' % viewurl, + archive_view.as_view( + model=model,), + name='%s_%s_list' % (app_name, model_name), + ), + ) + viewurl=viewurl+'(?P<year>\d{4})/' + urls.append( + url( + r'^%s$' % viewurl, + year_archive_view.as_view( + model=model,), + name='%s_%s_list_y' % (app_name, model_name), + ), + ) + viewurl=viewurl+'(?P<month>\d{2})/' + urls.append( + url( + r'^%s$' % viewurl, + month_archive_view.as_view( + model=model,), + name='%s_%s_list_ym' % (app_name, model_name), + ), + ) + viewurl=viewurl+'(?P<day>\d{2})/' + urls.append( + url( + r'^%s$' % viewurl, + day_archive_view.as_view( + model=model,), + name='%s_%s_list_ymd' % (app_name, model_name), + ), + ) + urls.append( + url( + r'^%s(?P<slug>[0-9a-zA-Z_-]+)/$' % viewurl, + detail_view.as_view( + model=model,), + name='%s_%s_detail' % (app_name, model_name), + ), + ) + return urls + +urls = get_urls() +urlpatterns = patterns(*urls) diff --git a/newsbox/utils.py b/newsbox/utils.py new file mode 100644 index 0000000..c53eac0 --- /dev/null +++ b/newsbox/utils.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- + +def get_newsmodels_list(): + from django.db.models import get_app, get_models + pass diff --git a/newsbox/views.py b/newsbox/views.py new file mode 100644 index 0000000..f47c0ba --- /dev/null +++ b/newsbox/views.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.http import Http404, HttpResponse +from django.shortcuts import render_to_response, get_object_or_404 +from django.template.context import RequestContext +from django.utils.translation import ugettext as _ +from django.db.models.loading import get_model +from django.views.generic.dates import DateDetailView, ArchiveIndexView, \ + YearArchiveView, MonthArchiveView, DayArchiveView + +from .models import NewsboxBase + +class NewsboxBaseArchiveView(object): + """ + This view is responsible for displaying a list of newsbox + """ + date_field = "newsbox_date" + slug_field = "newsbox_slug" + paginate_by = 10 + make_object_list = True + allow_future = True + template_name = "newsbox/list.html" + context_object_name = 'newsset' + title = None + + def update_context_data(self, context, **kwargs): + with_pager = context['is_paginated'] + context['newsset'].number = context['page_obj'].number + context['newsset'].has_previous = context['page_obj'].has_previous + context['newsset'].has_next = context['page_obj'].has_next + context['newsset'].next_page_number = context['page_obj'].next_page_number + context['newsset'].previous_page_number = context['page_obj'].previous_page_number + context['newsset'].paginator = context['paginator'] + if self.title == None: + title = self.model._meta.verbose_name_plural.capitalize() + else: + title=self.title + context.update({ + 'instance': None, + 'title': title, + 'title_url': '', + 'newsbox_opts':self.model._newsbox_meta, + 'with_pager': with_pager, + }) + return context + + def get_queryset(self): + if self.request.user.is_staff: + return self.model.objects.all() + else: + return self.model.objects.published() + +class NewsboxArchiveView(NewsboxBaseArchiveView, ArchiveIndexView): + def get_context_data(self, **kwargs): + context = super(NewsboxArchiveView, self).get_context_data(**kwargs) + NewsboxBaseArchiveView.update_context_data(self, context, **kwargs) + return context + +class NewsboxYearArchiveView(NewsboxBaseArchiveView, YearArchiveView): + def get_context_data(self, **kwargs): + context = super(NewsboxYearArchiveView, self).get_context_data(**kwargs) + NewsboxBaseArchiveView.update_context_data(self, context, **kwargs) + return context + + def get_queryset(self): + if self.request.user.is_staff: + return self.model.objects.all() + else: + return self.model.objects.published() + +class NewsboxMonthArchiveView(NewsboxBaseArchiveView, MonthArchiveView): + month_format = "%m" + def get_context_data(self, **kwargs): + context = super(NewsboxMonthArchiveView, self).get_context_data(**kwargs) + NewsboxBaseArchiveView.update_context_data(self, context, **kwargs) + return context + +class NewsboxDayArchiveView(NewsboxBaseArchiveView, DayArchiveView): + month_format = "%m" + def get_context_data(self, **kwargs): + context = super(NewsboxDayArchiveView, self).get_context_data(**kwargs) + NewsboxBaseArchiveView.update_context_data(self, context, **kwargs) + return context + + + +class NewsboxDetailView(DateDetailView): + """ + This view is responsible for displaying a newsbox + """ + month_format = "%m" + date_field = "newsbox_date" + slug_field = "newsbox_slug" + template_name = "newsbox/detail.html" + context_object_name = "news" + allow_future = True + + def get_context_data(self, **kwargs): + context = super(NewsboxDetailView, self).get_context_data(**kwargs) + if 'NewsboxCMSBase' in (base.__name__ for base in self.model.__bases__): + from menus.utils import set_language_changer + set_language_changer(self.request, self.object.get_absolute_url) + return context + + def get_object(self): + # We check user permission + obj = super(NewsboxDetailView, self).get_object() + if( + not obj.is_published() + and not obj.has_change_permission(self.request) + ): + raise Http404 + return obj diff --git a/newsbox_cms/__init__.py b/newsbox_cms/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/newsbox_cms/admin.py b/newsbox_cms/admin.py new file mode 100644 index 0000000..14388ef --- /dev/null +++ b/newsbox_cms/admin.py @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.contrib import admin +from django.core.urlresolvers import reverse +from django.utils import formats +from django.utils.translation import ugettext_lazy as _ +from django.utils import six + +try: + from cms.admin.placeholderadmin import FrontendEditableAdminMixin, PlaceholderAdminMixin +except ImportError: + # temporary django-cms backward compat + from cms.admin.placeholderadmin import ( + FrontendEditableAdmin as FrontendEditableAdminMixin, + PlaceholderAdmin as PlaceholderAdminMixin + ) + +from newsbox.admin import NewsboxBaseAdmin, remove_field_from_fieldsets, add_fields_to_fieldset + + +class CustomModelCMSAdmin(admin.ModelAdmin): + class Media: + css = { + "all": ("newsbox_cms/custom_model.css",) + } + + +def CustomModelCMSAdminFactory( + object_title=None, + edit_link_short_description=_('title'), + edit_link_admin_order_field=None, +): + class klass(CustomModelCMSAdmin): + + def edit_link_title(self, obj, func_or_attr=None): + if func_or_attr is not None: + if isinstance(func_or_attr, basestring): + if not hasattr(obj, func_or_attr): + raise ValueError( + 'func_or_attr is a string, it needs to be' + ' an object attribute (eventualy a function)' + ) + + attr = getattr(obj, func_or_attr) + if callable(attr): + title = attr(obj) + else: + title = attr + + elif callable(func_or_attr): + title = func_or_attr(obj) + else: + raise ValueError('func_or_attr needs to be either a string or a collable') + + else: + title = six.text_type(obj) + return title + + def edit_link(self, obj): + """ + build the change list edit link + """ + output = '' + edit_url = reverse( + 'admin:%s_%s_change' % (obj._meta.app_label, obj._meta.module_name), + args=[obj.pk]) + + show_url = None + if hasattr(obj, 'get_absolute_url'): + show_url = obj.get_absolute_url() + + output = '<a class="edit" href="{edit_url}" title="{edit_label}"></a>' + + if show_url: + output += '<a class="title" href="{show_url}" target="_parent" title="{show_label}">{title}</a>' + else: + output += '<span class="title">{title}</span>' + + return output.format( + edit_url=edit_url, show_url=show_url, show_label=_("show object's page"), + title=self.edit_link_title(obj, object_title), edit_label=_("edit object's parameters")) + + edit_link.allow_tags = True + edit_link.short_description = edit_link_short_description + edit_link.admin_order_field = edit_link_admin_order_field + + + def get_list_display(self, request): + list_display = super(CustomModelCMSAdmin, self).get_list_display(request) + list_display = list(list_display) + del list_display[0] + list_display.insert(0, 'edit_link') + return list_display + + def get_list_display_links(self, request, list_display): + return [] + + return klass + + +def newsbox_admin_title(obj): + return '{date}<br/>{title}'.format( + date=formats.date_format(obj.newsbox_date, 'DATE_FORMAT'), + title=six.text_type(obj) + ) + + +class NewsboxCMSAdmin( + #XXX: hvad TranslatableAdmin doesn't support admin_order_field on translated field + # CustomModelCMSAdminFactory(edit_link_admin_order_field='newsbox_title'), + CustomModelCMSAdminFactory(object_title=newsbox_admin_title, edit_link_admin_order_field='newsbox_date'), + FrontendEditableAdminMixin, + PlaceholderAdminMixin, + NewsboxBaseAdmin +): + + def __init__(self, *args, **kwargs): + # We manage the edit link ourself + self.list_display_links = (None, ) + return super(NewsboxCMSAdmin, self).__init__(*args, **kwargs) + + def get_fieldsets(self, request, obj=None): + fieldsets = super(NewsboxCMSAdmin, self).get_fieldsets(request, obj) + remove_field_from_fieldsets('newsbox_body', fieldsets) + add_fields_to_fieldset( + ['newsbox_summary'], + fieldsets, + same_fieldset_as='newsbox_published', + replace_existing_field=True, + remove_empty_fieldset=True, + ) + return fieldsets + + def get_list_display(self, request): + list_display = super(NewsboxCMSAdmin, self).get_list_display(request) + list_display.remove('newsbox_date') + list_display.remove('get_newsbox_slug') + return list_display diff --git a/newsbox_cms/cms_plugins.py b/newsbox_cms/cms_plugins.py new file mode 100644 index 0000000..d42181a --- /dev/null +++ b/newsbox_cms/cms_plugins.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.utils.translation import ugettext as _ +from django.db import models +from django.contrib import admin +from cms.plugin_base import CMSPluginBase +from newsbox.models import NewsboxBase + +class NewsboxPluginBase(CMSPluginBase): + name = _("News list") # Name of the plugin + render_template = "newsbox_cms/list-cms.html" # template to render the plugin + raw_id_fields = ('page_link',) + + def render(self, context, instance, placeholder): + from django.db.models.loading import get_model + + NewsboxModel = instance.newsbox_model + + if not NewsboxModel or not issubclass(NewsboxModel, NewsboxBase): + raise Exception(_("The choosen news type to display is invalid")) + + if instance.numitems > 0 : + with_pager = instance.with_pager + + if with_pager : + from django.core.paginator import Paginator, \ + EmptyPage, PageNotAnInteger + + paginator = Paginator(NewsboxModel.objects.published(), + instance.numitems) + page = context['request'].GET.get('page') + try: + newsset = paginator.page(page) + except PageNotAnInteger: + # If page is not an integer, deliver first page. + newsset = paginator.page(1) + except EmptyPage: + # If page is out of range (e.g. 9999), deliver last page of results. + newsset = paginator.page(paginator.num_pages) + else : + newsset = NewsboxModel.objects.published()[:instance.numitems] + else : + newsset = NewsboxModel.objects.published() + with_pager = False + context.update({ + 'instance': instance, + 'title': instance.title, + 'newsset':newsset, + 'newsbox_opts':NewsboxModel._newsbox_meta, + 'with_pager':with_pager, + }) + + if instance.page_link: + context.update({ + 'title_url' : instance.page_link.get_absolute_url(), + 'all_news_url': instance.page_link.get_absolute_url(), + }) + return context + + class Meta: + abstract = True diff --git a/newsbox_cms/locale/fr/LC_MESSAGES/django.mo b/newsbox_cms/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..27fc1c4239e93e2dacb771170c4c9f4feb1dca80 GIT binary patch literal 1538 zcmZ{k&u<e)6vu}G1>7H?fM})m@D!*BpiS0>18fMYn>Z-##&MGkCoW^}*cr5*v1Voi zK5?x22ee!`aBTmCs;X2eS0p6F8FApsf6zm}vuooGw5z=Rc;~%&@6DU{@@nqbFAUEa z$k&i3kT3l2BY5F?2z~~R!PDSR-~#v<JPZB}o&sNjpM$T!Ti{#pOYq7^rG6E>itkPE zI5-9gd<1&Cr{Em;$3*`O{1HB0fZp!nF~-h=EieM_ffvBXpwHt^@ErIY{2qKW(JvvG z&wmHJ4sy`P{}nF+pMdk=U*K2ZYY>0zAG{EreGKvE@@u|ECm}V+`_Cs>@NtlCQIAh2 z2EJw|AV(ocY4$X;jFfm_X~YMDtw}q|_?UR{Y2JP7K9;;$b>*7{)xDg4u*@eOS=+nK zq;;&F54*w;yc9kTf0EObmT?zpKAa~w&<|*=^NNO=aa?ZhAkV42R0D5aDz*hrX{e20 z$)2Fzp4L{VLPc&o5>;o?l2rRVlPOE2%do@0s}^0+hbMCIRGdJh(vj}o7d>~$*UIpr zaKcz-_mFEvfg-xXWyff59c-k*T^LHOBI-0(e`wxm(cRYe&c;@|wk<~5xM0%`WEy;z z4{VU=h-#g!Bv>_qJ8TNpxDydI!us_fYy^#v>S5Hlc{QwuAq<0Uu`j*z|FpYSFYRJ( zU62^AY{s272oZBN$Wh545qua?+-%?3^_ks@<8L#$sLkN^I~$m9Zfv$@$EYucwN<U0 zQ1FV<M&!gpw}j4-Y8jR1#tOHxo2&;nW_CV$Uznh!dOF3$MRcPpU9FSlhG)ULHbWbc z8Wo>*rLj!q&y@v5x2b-4xyBNmJAsaZ_-3_~LU_;RxJY;KyJgLOU-ocgxf0$&s-l9E z<)UqHo0n!g4r^%A&olkh<7BIw#jo1L=x}so#jj;;J?x@=4lgQ9!TXDJ@RWF&wppYd zj=MC)5R8ODhvA5nZ0#nko#NP2%fpHPZ(azNak9B|g2iZNKLyp4s=@uhAUFx@rn6Cu zg&!yB;Hi=*@qMnG_w8pxu!Em59hmR(W-uBDzhQ^JAC%kAhMQguY|4KvRbAnq{R=mM Btla<r literal 0 HcmV?d00001 diff --git a/newsbox_cms/locale/fr/LC_MESSAGES/django.po b/newsbox_cms/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..39af73d --- /dev/null +++ b/newsbox_cms/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,84 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-02-20 10:29+0100\n" +"PO-Revision-Date: 2014-02-20 10:31+0100\n" +"Last-Translator: \n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: admin.py:20 +msgid "title" +msgstr "Titre" + +#: admin.py:70 +msgid "show object's page" +msgstr "Afficher la page de l'objet" + +#: admin.py:71 +msgid "edit object's parameters" +msgstr "Éditer les paramètres de l'objet" + +#: cms_plugins.py:10 +msgid "News list" +msgstr "Liste d'actualités" + +#: cms_plugins.py:19 +msgid "The choosen news type to display is invalid" +msgstr "Le type d'actualité à afficher choisi est invalide" + +#: models.py:12 +msgid "Title" +msgstr "Titre" + +#: models.py:14 +msgid "Title to display before the list" +msgstr "Titre à afficher avant la liste" + +#: models.py:16 +msgid "Number of news" +msgstr "Nombre d'actualités" + +#: models.py:18 +msgid "Number of news to display. \"0\" allow you to display ALL news" +msgstr "numbre d'actualités à afficher. Saisir \"0\" permet de TOUTES les afficher" + +#: models.py:21 +msgid "Display a pager" +msgstr "Affiche une pagination" + +#: models.py:24 +msgid "All news page" +msgstr "Toutes les pages des actualités" + +#: models.py:26 +msgid "Page displaying all news" +msgstr "Affichage de toutes les actualités" + +#: models.py:31 +#, python-format +msgid "Display of a news" +msgid_plural "Display of %(nb)d news" +msgstr[0] "Affichage de l'actualité" +msgstr[1] "Affichage de %(nb)d actualités" + +#: models.py:35 +msgid "Display of all news" +msgstr "Affichage de toutes les actualités" + +#: templates/newsbox_cms/list-cms.html:11 +msgid "Read more" +msgstr "Lire la suite" + +#~ msgid "News type to display" +#~ msgstr "Type d'actualité à afficher" diff --git a/newsbox_cms/models.py b/newsbox_cms/models.py new file mode 100644 index 0000000..3a28d46 --- /dev/null +++ b/newsbox_cms/models.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.utils.translation import ugettext_lazy as _, ungettext_lazy +from django.utils import six +from django.utils.encoding import python_2_unicode_compatible +from django.db import models +from cms.models.pluginmodel import CMSPlugin +from cms.models.fields import PageField, PlaceholderField +from djangocms_text_ckeditor.fields import HTMLField + +from newsbox.models import NewsboxModelBase + + +def newsboxcms_mcls_processor(mcls, class_name, class_bases, class_attrs, base, newsbox_opts): + class_attrs['newsbox_summary'] = HTMLField( + verbose_name=_('summary')) + class_attrs['newsbox_body'] = PlaceholderField( + 'newsbox_body', + verbose_name=_('body')) + + if 'newsbox_body' in newsbox_opts['trans_fieldnames']: + newsbox_opts['trans_fieldnames'].remove('newsbox_body') + + +@python_2_unicode_compatible +class NewsboxPluginBase(CMSPlugin): + title = models.CharField( + verbose_name=_('Title'), + max_length=255, blank=True, null=True, + help_text=_('Title to display before the list')) + numitems = models.PositiveSmallIntegerField( + verbose_name=_('Number of news'), + default=2, + help_text=_('Number of news to display. ' + '"0" allow you to display ALL news')) + with_pager = models.BooleanField( + verbose_name=_('Display a pager'), + default=False) + + page_link = PageField(verbose_name=_('All news page'), + null=True, blank=True, + help_text=_('Page displaying all news')) + + def __str__(self): + if self.numitems > 0: + return six.text_type(ungettext_lazy( + 'Display of a news', + 'Display of %(nb)d news', + self.numitems + ) % {'nb':self.numitems}) + return six.text_type(_('Display of all news')) + + class Meta: + abstract = True + + +class NewsboxCMSBase(six.with_metaclass(NewsboxModelBase, models.Model)): + + class Meta: + abstract = True + newsbox_metaclass_base_processor = 'newsboxcms_mcls_processor' diff --git a/newsbox_cms/static/newsbox_cms/custom_model.css b/newsbox_cms/static/newsbox_cms/custom_model.css new file mode 100644 index 0000000..32b677e --- /dev/null +++ b/newsbox_cms/static/newsbox_cms/custom_model.css @@ -0,0 +1,11 @@ + +body.change-list #result_list td a.edit { + float:right; + background:url("../cms/img/pagetree/sprite.png") no-repeat scroll 0px 0px transparent; + width:18px; + height:18px; + display:inline-block; + background-position: -40px -20px; + margin-top: 0px; + vertical-align: middle; +} diff --git a/newsbox_cms/templates/newsbox_cms/detail-cms.html b/newsbox_cms/templates/newsbox_cms/detail-cms.html new file mode 100644 index 0000000..9b4bdc6 --- /dev/null +++ b/newsbox_cms/templates/newsbox_cms/detail-cms.html @@ -0,0 +1,22 @@ +{% extends "newsbox/detail.html" %} +{% load i18n %} +{% load get_placeholder_content cms_tags %} + +{% block newsbox_detail_header %} + <header> + <h1>{% render_model news "newsbox_title" %}</h1> + <time datetime="{{ news.newsbox_date }}">{{ news.newsbox_date|date:'d M. Y' }}</time> + </header> +{% endblock %} + +{% block newsbox_detail_item_content %} + <div class="content"> + {% render_placeholder news.newsbox_body %} + + {% get_placeholder_content news.newsbox_body as body %} + {% if not body %} + {{ news.newsbox_summary|safe }} + {% endif %} + {% endget_placeholder_content %} + </div> +{% endblock %} diff --git a/newsbox_cms/templates/newsbox_cms/list-cms.html b/newsbox_cms/templates/newsbox_cms/list-cms.html new file mode 100644 index 0000000..812f8b8 --- /dev/null +++ b/newsbox_cms/templates/newsbox_cms/list-cms.html @@ -0,0 +1,18 @@ +{% extends "newsbox/list.html" %} +{% load i18n %} +{% load get_placeholder_content %} + +{% block newsbox_list_item_content %} + + <div class="summary"> + {{ news.newsbox_summary|safe }} + {% get_placeholder_content news.newsbox_body as body %} + + {% if body %} + <p class="readmore"><a href="{{ news.get_absolute_url }}"> + {% trans "Read more" %} + </a></p> + {% endif %} + {% endget_placeholder_content %} + </div> +{% endblock %} diff --git a/newsbox_hvad/__init__.py b/newsbox_hvad/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/newsbox_hvad/admin.py b/newsbox_hvad/admin.py new file mode 100644 index 0000000..fb474b0 --- /dev/null +++ b/newsbox_hvad/admin.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +import copy + +from django.conf import settings +from hvad.admin import TranslatableAdmin +from hvad.forms import translatable_modelform_factory +from django.utils.translation import ugettext_lazy as _ +from django.contrib.admin.util import flatten_fieldsets +from django.utils.functional import curry + + +def edit_translation_links(obj): + output = '' + for lang in obj.get_available_languages(): + output += ( + '<a href="./%s/?language=%s" ' + 'target="_parent" title="Edit this %s in %s">%s' + '</a>' + ) % (obj.pk, lang, obj._meta.verbose_name, lang.upper(), lang.upper(),) + return output +edit_translation_links.allow_tags = True +edit_translation_links.short_description = _('translations') + + + +class NewsboxHVADBaseAdmin(TranslatableAdmin): + + #XXX: hvad TranslatableAdmin doesn't support search_fields + # search_fields = ['newsbox_title', 'newsbox_summary', ] + # date_hierarchy = 'newsbox_publication_start_date' + + def get_list_display(self, request): + list_display = super(NewsboxHVADBaseAdmin, self).get_list_display(request) + # prevent modifying class list_display variable + list_display = copy.deepcopy(list_display) + if settings.LANGUAGES and len(settings.LANGUAGES) > 1: + list_display.insert(1, edit_translation_links) + + return list_display + + def get_form(self, request, obj=None, **kwargs): + """ + This function is a workaround to an hvad issue. It doesn't use + get_fieldsets function. + + Returns a Form class for use in the admin add view. This is used by + add_view and change_view. + """ + fieldsets = self.get_fieldsets(request, obj) + if fieldsets: + fields = flatten_fieldsets(fieldsets) + else: + fields = None + if self.exclude is None: + exclude = [] + else: + exclude = list(self.exclude) + exclude.extend(kwargs.get("exclude", [])) + exclude.extend(self.get_readonly_fields(request, obj)) + # Exclude language_code, adding it again to the instance is done by + # the LanguageAwareCleanMixin (see translatable_modelform_factory) + exclude.append('language_code') + old_formfield_callback = curry(self.formfield_for_dbfield, + request=request) + defaults = { + "form": self.form, + "fields": fields, + "exclude": exclude, + "formfield_callback": old_formfield_callback, + } + defaults.update(kwargs) + language = self._language(request) + return translatable_modelform_factory(language, self.model, **defaults) + + +class NewsboxHVADAdmin(NewsboxHVADBaseAdmin): + pass diff --git a/newsbox_hvad/models.py b/newsbox_hvad/models.py new file mode 100644 index 0000000..18960f0 --- /dev/null +++ b/newsbox_hvad/models.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +import sys + +from django.db import models +from django.core.urlresolvers import reverse +from django.utils.translation import ugettext_lazy as _, get_language, activate +from django.utils import six +from django.utils.encoding import python_2_unicode_compatible +from hvad.manager import TranslationManager +from hvad.models import TranslatableModel, TranslatedFields, \ + TranslatableModelBase +from newsbox.models import NewsboxModelBase, NewsboxManager, \ + NewsboxBase, newsbox_models + + +class NewsboxHVADManager(TranslationManager, NewsboxManager): + pass + +def newsboxhvad_mcls_processor(mcls, class_name, class_bases, class_attrs, base, newsbox_opts): + translatedFields={} + for trans_field in newsbox_opts['trans_fieldnames']: + translatedFields[trans_field] = class_attrs.pop(trans_field) + class_attrs['translations'] = TranslatedFields(**translatedFields) + class_attrs['newsbox_objects'] = NewsboxHVADManager() + #class_attrs['default_manager'] = class_attrs['newsbox_objects'] + + +class NewsboxHVADModelBase(NewsboxModelBase, TranslatableModelBase): + pass + + +@python_2_unicode_compatible +class NewsboxHVADBase(six.with_metaclass(NewsboxHVADModelBase, TranslatableModel)): + """ + Define News which expires in time and will not be displayed in front + """ + + default_manager = NewsboxHVADManager() + objects = default_manager + + def __str__(self): + return self.lazy_translation_getter( + 'newsbox_title', + _('News n° %s') % self.pk) + + def get_slug(self, language=None, *args, **kwargs): + """ + Returns the slug for this object for the given language. + """ + if language is None or language == self.language_code: + return self.safe_translation_getter('newsbox_slug') + else: + instance = self.__class__.objects.language(language).get(pk=self.pk) + return instance.safe_translation_getter('newsbox_slug') + + def get_absolute_url(self, language=None, *args, **kwargs): + """ + Build url for the given language. + """ + current_language = get_language() + + if not language: + language = current_language + + if language in self.get_available_languages(): + activate(language) + url = reverse(self._newsbox_meta['detail_url_name'], args=( + self.newsbox_date.strftime("%Y"), + self.newsbox_date.strftime("%m"), + self.newsbox_date.strftime("%d"), + self.get_slug(language=language),)) + activate(current_language) + return url + + return "./" + + + class Meta: + abstract = True + verbose_name = _('news') + verbose_name_plural = _('news') + #newsbox_metaclass_base_processor = 'newsboxhvad_mcls_processor' + newsbox_metaclass_final_processor = 'newsboxhvad_mcls_processor' diff --git a/newsbox_hvad/urls.py b/newsbox_hvad/urls.py new file mode 100644 index 0000000..ca160a4 --- /dev/null +++ b/newsbox_hvad/urls.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.conf.urls import patterns +from newsbox.urls import get_urls + +from .views import NewsboxHVADDetailView + +urls = get_urls(detail_view=NewsboxHVADDetailView) +urlpatterns = patterns(*urls) diff --git a/newsbox_hvad/views.py b/newsbox_hvad/views.py new file mode 100644 index 0000000..209f38a --- /dev/null +++ b/newsbox_hvad/views.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from newsbox.views import NewsboxDetailView + +class NewsboxHVADDetailView(NewsboxDetailView): + + def get_queryset(self): + """ + As slug_field is translated, we need to use translation aware + queryset. + """ + return self.model.objects.using_translations() diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..9c201cf --- /dev/null +++ b/setup.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +from setuptools import setup, find_packages +import os +import newsbox + + +CLASSIFIERS = [ + 'Development Status :: 5 - Production/Stable', + 'Environment :: Web Environment', + 'Framework :: Django', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: BSD License', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', + 'Topic :: Software Development', + 'Topic :: Software Development :: Libraries :: Application Frameworks', + "Programming Language :: Python :: 2.6", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3.3", +] + +setup( + author="Dylann Cordel", + author_email="d.cordel@webu.coop", + name='django-newsbox', + version=newsbox.__version__, + description='A Django and Django CMS APP providing news support', + long_description=open(os.path.join(os.path.dirname(__file__), 'README.md')).read(), + url='https://dev.webu.coop/webu/django-newsbox', + license='BSD License', + platforms=['OS Independent'], + classifiers=CLASSIFIERS, + install_requires=[ + 'Django>=1.6,<1.7', + ], + packages=find_packages(exclude=["project", "project.*"]), + include_package_data=True, + zip_safe=False, +) diff --git a/test_requirements/django-1.6.txt b/test_requirements/django-1.6.txt new file mode 100644 index 0000000..9cec9f6 --- /dev/null +++ b/test_requirements/django-1.6.txt @@ -0,0 +1,3 @@ +-r requirements_base.txt +django>=1.6,<1.7 +https://github.com/KristianOellegaard/django-hvad/archive/master.zip#egg=hvad diff --git a/test_requirements/django-1.6_cms-3.0.txt b/test_requirements/django-1.6_cms-3.0.txt new file mode 100644 index 0000000..2b2c097 --- /dev/null +++ b/test_requirements/django-1.6_cms-3.0.txt @@ -0,0 +1,37 @@ +# Currently, 3.0 is not yet released, so we use the develop branch +git+https://github.com/divio/django-cms.git@develop#egg=django-cms + +# This is django-cms test requirements + +django>=1.6,<1.7 +django-reversion>=1.8 + +coverage==3.7 +python-coveralls==2.4.0 +docopt==0.6.1 +unittest-xml-reporting==1.0.3 +sphinx +Pillow==2.0 +django-classy-tags>=0.5 +South>=0.7.2 +html5lib>=0.90 +django-mptt>=0.6 +django-sekizai>=0.7 +argparse +dj-database-url +selenium +django-debug-toolbar +https://github.com/KristianOellegaard/django-hvad/archive/master.zip#egg=hvad +-e git+git://github.com/divio/djangocms-admin-style.git#egg=djangocms-admin-style +-e git+git://github.com/divio/djangocms-text-ckeditor.git#egg=djangocms-text-ckeditor +-e git+git://github.com/divio/djangocms-column.git#egg=djangocms-column +-e git+git://github.com/divio/djangocms-style.git#egg=djangocms-style +-e git+git://github.com/divio/djangocms-file.git#egg=djangocms-file +-e git+git://github.com/divio/djangocms-flash.git#egg=djangocms-flash +-e git+git://github.com/divio/djangocms-googlemap.git#egg=djangocms-googlemap +-e git+git://github.com/divio/djangocms-inherit.git#egg=djangocms-inherit +-e git+git://github.com/divio/djangocms-picture.git#egg=djangocms-picture +-e git+git://github.com/divio/djangocms-teaser.git#egg=djangocms-teaser +-e git+git://github.com/divio/djangocms-video.git#egg=djangocms-video +-e git+git://github.com/divio/djangocms-link.git#egg=djangocms-link +pyflakes diff --git a/test_requirements/requirements_base.txt b/test_requirements/requirements_base.txt new file mode 100644 index 0000000..66f9b96 --- /dev/null +++ b/test_requirements/requirements_base.txt @@ -0,0 +1,3 @@ +south>=0.7.2 +pytz +beautifulsoup4 diff --git a/tests/myapp/README.md b/tests/myapp/README.md new file mode 100644 index 0000000..635d779 --- /dev/null +++ b/tests/myapp/README.md @@ -0,0 +1,90 @@ +initial fixtures +================ + +## News + +If not precised, news have those default values : + +* newsbox_slug : news-%(pk)d +* newsbox_title : News %(pk)d +* newsbox_date : 2014-02-22 10:00:00 +* newsbox_publication_start_date : 1985-07-02 10:00:00 +* newsbox_published : True +* newsbox_summary : Summary of the news %(pk)d +* newsbox_body : Body of the news %(pk)d + +### List of all available test News + +1. A basic classic published news +2. A not published news via newsbox_published + * newsbox_published = False +3. A not published news via newsbox_publication_start_date + * newsbox_publication_start_date = 2020-01-01 10:00:00 +4. A published news without body + * newsbox_body = '' +5. A not published news via newsbox_published (same as #2) + * newsbox_published = False +6. A published news about an old event + * newsbox_date = 2005-07-15 10:00:00 +7. A published news about a future event + * newsbox_date = 2020-01-01 10:00:00 + +## NewsExpired + +If not precised, Expired news have default values from news for classic news +fields and those values for specific Expired news fields : + +* newsbox_publication_end_date : 2014-02-22 10:00:00 + +### List of all available test NewsExpired + +* from 1 to 4 : same as News +5. A not published news via his expiration's date + * newsbox_publication_end_date = 2000-01-01 10:00:00 +* from 6 to 7 : same as News + +## NewsSEO + +If not precised, SEO news have default values from news for classic news fields +and those values for specific SEO news fields : + +* newsbox_indexed : True +* newsbox_meta_description : Meta description of the news %(pk)d +* newsbox_meta_keywords : keyword1, keyword2, news-%(pk)d + +### List of all available test NewsExpired + +* from 1 to 5 : same as News +6. same as #6 of News but not indexed news via newsbox_indexed + * newsbox_indexed = False +7. same as #7 of News + +## NewsComplete + +If not precised, Complete news have default values from news for classic news +fields, from NewsSEO for seo fields, from NewsExpired for expired fields. + +### List of all available test NewsComplete + +* from 1 to 5 : same as NewsExpired +6. Same as #6 of NewsSEO +7. same as #7 of News + +## NewsExtended + +If not precised, Complete news have default values from news for classic news +fields, from NewsSEO for seo fields, from NewsExpired for expired fields and +those values for specific NewsExtended news fields : + +* general_field : Test +* content_field : Extra content of the news %(pk)d +* seo_field : Extra SEO of the news %(pk)d + +### List of all available test NewsExtended + +* from 1 to 7 : same as NewsComplete + +## Code used to generate test news + +You can see the code used to generate initial fixtures in utils.py in this +directory. diff --git a/tests/myapp/__init__.py b/tests/myapp/__init__.py new file mode 100644 index 0000000..40a96af --- /dev/null +++ b/tests/myapp/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/tests/myapp/admin.py b/tests/myapp/admin.py new file mode 100644 index 0000000..10fbc62 --- /dev/null +++ b/tests/myapp/admin.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +from django.contrib import admin +from newsbox.admin import NewsboxAdmin, NewsboxSEOAdmin, NewsboxExpiredAdmin + +from .models import News, NewsSEO, NewsExpired, NewsComplete, NewsExtended + +class NewsAdmin(NewsboxAdmin): + pass + +admin.site.register(News, NewsAdmin) + + +class NewsSEOAdmin(NewsboxSEOAdmin): + pass + +admin.site.register(NewsSEO, NewsSEOAdmin) + + +class NewsExpiredAdmin(NewsboxExpiredAdmin): + pass + +admin.site.register(NewsExpired, NewsExpiredAdmin) + + +class NewsCompleteAdmin(NewsboxSEOAdmin, NewsboxExpiredAdmin): + pass + +admin.site.register(NewsComplete, NewsCompleteAdmin) + + +class NewsExtendedAdmin(NewsboxSEOAdmin, NewsboxExpiredAdmin): + def get_fieldsets(self, request, obj=None): + fieldsets = super(NewsExtendedAdmin, self).get_fieldsets(request, obj) + fieldsets[0][1]['fields'].append('general_field') + fieldsets[2][1]['fields'].append('content_field') + fieldsets[3][1]['fields'].append('seo_field') + return fieldsets + + def get_list_display(self, request): + list_display = super(NewsExtendedAdmin, self).get_list_display(request) + list_display.append('seo_field') + return list_display + +admin.site.register(NewsExtended, NewsExtendedAdmin) diff --git a/tests/myapp/fixtures/tests_data.json b/tests/myapp/fixtures/tests_data.json new file mode 100644 index 0000000..7b70649 --- /dev/null +++ b/tests/myapp/fixtures/tests_data.json @@ -0,0 +1,632 @@ +[ +{ + "pk": 1, + "model": "myapp.news", + "fields": { + "newsbox_published": true, + "newsbox_slug": "news-1", + "newsbox_creation_date": "2014-03-11T13:54:03.213Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_summary": "Summary of the news 1", + "newsbox_body": "Body of the news 1", + "newsbox_changed_date": "2014-03-11T13:54:03.213Z", + "newsbox_title": "News 1" + } +}, +{ + "pk": 2, + "model": "myapp.news", + "fields": { + "newsbox_published": false, + "newsbox_slug": "news-2", + "newsbox_creation_date": "2014-03-11T13:54:03.398Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_summary": "Summary of the news 2", + "newsbox_body": "Body of the news 2", + "newsbox_changed_date": "2014-03-11T13:54:03.398Z", + "newsbox_title": "News 2" + } +}, +{ + "pk": 3, + "model": "myapp.news", + "fields": { + "newsbox_published": true, + "newsbox_slug": "news-3", + "newsbox_creation_date": "2014-03-11T13:54:03.598Z", + "newsbox_publication_start_date": "2020-01-01T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_summary": "Summary of the news 3", + "newsbox_body": "Body of the news 3", + "newsbox_changed_date": "2014-03-11T13:54:03.598Z", + "newsbox_title": "News 3" + } +}, +{ + "pk": 4, + "model": "myapp.news", + "fields": { + "newsbox_published": true, + "newsbox_slug": "news-4", + "newsbox_creation_date": "2014-03-11T13:54:03.882Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_summary": "Summary of the news 4", + "newsbox_body": "", + "newsbox_changed_date": "2014-03-11T13:54:03.882Z", + "newsbox_title": "News 4" + } +}, +{ + "pk": 5, + "model": "myapp.news", + "fields": { + "newsbox_published": false, + "newsbox_slug": "news-5", + "newsbox_creation_date": "2014-03-11T13:54:04.083Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_summary": "Summary of the news 5", + "newsbox_body": "Body of the news 5", + "newsbox_changed_date": "2014-03-11T13:54:04.083Z", + "newsbox_title": "News 5" + } +}, +{ + "pk": 6, + "model": "myapp.news", + "fields": { + "newsbox_published": true, + "newsbox_slug": "news-6", + "newsbox_creation_date": "2014-03-11T13:54:04.293Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2005-07-15T08:00:00Z", + "newsbox_summary": "Summary of the news 6", + "newsbox_body": "Body of the news 6", + "newsbox_changed_date": "2014-03-11T13:54:04.293Z", + "newsbox_title": "News 6" + } +}, +{ + "pk": 7, + "model": "myapp.news", + "fields": { + "newsbox_published": true, + "newsbox_slug": "news-7", + "newsbox_creation_date": "2014-03-11T13:54:04.502Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2020-01-01T08:00:00Z", + "newsbox_summary": "Summary of the news 7", + "newsbox_body": "Body of the news 7", + "newsbox_changed_date": "2014-03-11T13:54:04.503Z", + "newsbox_title": "News 7" + } +}, +{ + "pk": 1, + "model": "myapp.newsseo", + "fields": { + "newsbox_published": true, + "newsbox_meta_description": "Meta description of the news 1", + "newsbox_slug": "news-1", + "newsbox_creation_date": "2014-03-11T13:54:01.813Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-1", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_summary": "Summary of the news 1", + "newsbox_body": "Body of the news 1", + "newsbox_changed_date": "2014-03-11T13:54:01.813Z", + "newsbox_title": "News 1" + } +}, +{ + "pk": 2, + "model": "myapp.newsseo", + "fields": { + "newsbox_published": false, + "newsbox_meta_description": "Meta description of the news 2", + "newsbox_slug": "news-2", + "newsbox_creation_date": "2014-03-11T13:54:02.005Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-2", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_summary": "Summary of the news 2", + "newsbox_body": "Body of the news 2", + "newsbox_changed_date": "2014-03-11T13:54:02.005Z", + "newsbox_title": "News 2" + } +}, +{ + "pk": 3, + "model": "myapp.newsseo", + "fields": { + "newsbox_published": true, + "newsbox_meta_description": "Meta description of the news 3", + "newsbox_slug": "news-3", + "newsbox_creation_date": "2014-03-11T13:54:02.201Z", + "newsbox_publication_start_date": "2020-01-01T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-3", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_summary": "Summary of the news 3", + "newsbox_body": "Body of the news 3", + "newsbox_changed_date": "2014-03-11T13:54:02.201Z", + "newsbox_title": "News 3" + } +}, +{ + "pk": 4, + "model": "myapp.newsseo", + "fields": { + "newsbox_published": true, + "newsbox_meta_description": "Meta description of the news 4", + "newsbox_slug": "news-4", + "newsbox_creation_date": "2014-03-11T13:54:02.408Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-4", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_summary": "Summary of the news 4", + "newsbox_body": "", + "newsbox_changed_date": "2014-03-11T13:54:02.408Z", + "newsbox_title": "News 4" + } +}, +{ + "pk": 5, + "model": "myapp.newsseo", + "fields": { + "newsbox_published": false, + "newsbox_meta_description": "Meta description of the news 5", + "newsbox_slug": "news-5", + "newsbox_creation_date": "2014-03-11T13:54:02.602Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-5", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_summary": "Summary of the news 5", + "newsbox_body": "Body of the news 5", + "newsbox_changed_date": "2014-03-11T13:54:02.602Z", + "newsbox_title": "News 5" + } +}, +{ + "pk": 6, + "model": "myapp.newsseo", + "fields": { + "newsbox_published": true, + "newsbox_meta_description": "Meta description of the news 6", + "newsbox_slug": "news-6", + "newsbox_creation_date": "2014-03-11T13:54:02.810Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-6", + "newsbox_date": "2005-07-15T08:00:00Z", + "newsbox_indexed": false, + "newsbox_summary": "Summary of the news 6", + "newsbox_body": "Body of the news 6", + "newsbox_changed_date": "2014-03-11T13:54:02.810Z", + "newsbox_title": "News 6" + } +}, +{ + "pk": 7, + "model": "myapp.newsseo", + "fields": { + "newsbox_published": true, + "newsbox_meta_description": "Meta description of the news 7", + "newsbox_slug": "news-7", + "newsbox_creation_date": "2014-03-11T13:54:03.019Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-7", + "newsbox_date": "2020-01-01T08:00:00Z", + "newsbox_indexed": true, + "newsbox_summary": "Summary of the news 7", + "newsbox_body": "Body of the news 7", + "newsbox_changed_date": "2014-03-11T13:54:03.019Z", + "newsbox_title": "News 7" + } +}, +{ + "pk": 1, + "model": "myapp.newsexpired", + "fields": { + "newsbox_published": true, + "newsbox_slug": "news-1", + "newsbox_changed_date": "2014-03-11T13:53:50.409Z", + "newsbox_creation_date": "2014-03-11T13:53:50.409Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_summary": "Summary of the news 1", + "newsbox_body": "Body of the news 1", + "newsbox_publication_end_date": null, + "newsbox_title": "News 1" + } +}, +{ + "pk": 2, + "model": "myapp.newsexpired", + "fields": { + "newsbox_published": false, + "newsbox_slug": "news-2", + "newsbox_changed_date": "2014-03-11T13:53:50.593Z", + "newsbox_creation_date": "2014-03-11T13:53:50.593Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_summary": "Summary of the news 2", + "newsbox_body": "Body of the news 2", + "newsbox_publication_end_date": null, + "newsbox_title": "News 2" + } +}, +{ + "pk": 3, + "model": "myapp.newsexpired", + "fields": { + "newsbox_published": true, + "newsbox_slug": "news-3", + "newsbox_changed_date": "2014-03-11T13:53:50.795Z", + "newsbox_creation_date": "2014-03-11T13:53:50.795Z", + "newsbox_publication_start_date": "2020-01-01T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_summary": "Summary of the news 3", + "newsbox_body": "Body of the news 3", + "newsbox_publication_end_date": null, + "newsbox_title": "News 3" + } +}, +{ + "pk": 4, + "model": "myapp.newsexpired", + "fields": { + "newsbox_published": true, + "newsbox_slug": "news-4", + "newsbox_changed_date": "2014-03-11T13:53:50.988Z", + "newsbox_creation_date": "2014-03-11T13:53:50.988Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_summary": "Summary of the news 4", + "newsbox_body": "", + "newsbox_publication_end_date": null, + "newsbox_title": "News 4" + } +}, +{ + "pk": 5, + "model": "myapp.newsexpired", + "fields": { + "newsbox_published": true, + "newsbox_slug": "news-5", + "newsbox_changed_date": "2014-03-11T13:53:51.196Z", + "newsbox_creation_date": "2014-03-11T13:53:51.196Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_summary": "Summary of the news 5", + "newsbox_body": "Body of the news 5", + "newsbox_publication_end_date": "2000-01-01T08:00:00Z", + "newsbox_title": "News 5" + } +}, +{ + "pk": 6, + "model": "myapp.newsexpired", + "fields": { + "newsbox_published": true, + "newsbox_slug": "news-6", + "newsbox_changed_date": "2014-03-11T13:53:51.406Z", + "newsbox_creation_date": "2014-03-11T13:53:51.406Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2005-07-15T08:00:00Z", + "newsbox_summary": "Summary of the news 6", + "newsbox_body": "Body of the news 6", + "newsbox_publication_end_date": null, + "newsbox_title": "News 6" + } +}, +{ + "pk": 7, + "model": "myapp.newsexpired", + "fields": { + "newsbox_published": true, + "newsbox_slug": "news-7", + "newsbox_changed_date": "2014-03-11T13:53:51.589Z", + "newsbox_creation_date": "2014-03-11T13:53:51.589Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2020-01-01T08:00:00Z", + "newsbox_summary": "Summary of the news 7", + "newsbox_body": "Body of the news 7", + "newsbox_publication_end_date": null, + "newsbox_title": "News 7" + } +}, +{ + "pk": 1, + "model": "myapp.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_meta_description": "Meta description of the news 1", + "newsbox_slug": "news-1", + "newsbox_changed_date": "2014-03-11T13:53:28.605Z", + "newsbox_creation_date": "2014-03-11T13:53:28.605Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-1", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_summary": "Summary of the news 1", + "newsbox_body": "Body of the news 1", + "newsbox_publication_end_date": null, + "newsbox_title": "News 1" + } +}, +{ + "pk": 2, + "model": "myapp.newscomplete", + "fields": { + "newsbox_published": false, + "newsbox_meta_description": "Meta description of the news 2", + "newsbox_slug": "news-2", + "newsbox_changed_date": "2014-03-11T13:53:28.763Z", + "newsbox_creation_date": "2014-03-11T13:53:28.763Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-2", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_summary": "Summary of the news 2", + "newsbox_body": "Body of the news 2", + "newsbox_publication_end_date": null, + "newsbox_title": "News 2" + } +}, +{ + "pk": 3, + "model": "myapp.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_meta_description": "Meta description of the news 3", + "newsbox_slug": "news-3", + "newsbox_changed_date": "2014-03-11T13:53:28.947Z", + "newsbox_creation_date": "2014-03-11T13:53:28.947Z", + "newsbox_publication_start_date": "2020-01-01T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-3", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_summary": "Summary of the news 3", + "newsbox_body": "Body of the news 3", + "newsbox_publication_end_date": null, + "newsbox_title": "News 3" + } +}, +{ + "pk": 4, + "model": "myapp.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_meta_description": "Meta description of the news 4", + "newsbox_slug": "news-4", + "newsbox_changed_date": "2014-03-11T13:53:29.125Z", + "newsbox_creation_date": "2014-03-11T13:53:29.125Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-4", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_summary": "Summary of the news 4", + "newsbox_body": "", + "newsbox_publication_end_date": null, + "newsbox_title": "News 4" + } +}, +{ + "pk": 5, + "model": "myapp.newscomplete", + "fields": { + "newsbox_published": false, + "newsbox_meta_description": "Meta description of the news 5", + "newsbox_slug": "news-5", + "newsbox_changed_date": "2014-03-11T13:53:29.368Z", + "newsbox_creation_date": "2014-03-11T13:53:29.368Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-5", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_summary": "Summary of the news 5", + "newsbox_body": "Body of the news 5", + "newsbox_publication_end_date": "2000-01-01T08:00:00Z", + "newsbox_title": "News 5" + } +}, +{ + "pk": 6, + "model": "myapp.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_meta_description": "Meta description of the news 6", + "newsbox_slug": "news-6", + "newsbox_changed_date": "2014-03-11T13:53:29.594Z", + "newsbox_creation_date": "2014-03-11T13:53:29.594Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-6", + "newsbox_date": "2005-07-15T08:00:00Z", + "newsbox_indexed": false, + "newsbox_summary": "Summary of the news 6", + "newsbox_body": "Body of the news 6", + "newsbox_publication_end_date": null, + "newsbox_title": "News 6" + } +}, +{ + "pk": 7, + "model": "myapp.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_meta_description": "Meta description of the news 7", + "newsbox_slug": "news-7", + "newsbox_changed_date": "2014-03-11T13:53:29.787Z", + "newsbox_creation_date": "2014-03-11T13:53:29.787Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-7", + "newsbox_date": "2020-01-01T08:00:00Z", + "newsbox_indexed": true, + "newsbox_summary": "Summary of the news 7", + "newsbox_body": "Body of the news 7", + "newsbox_publication_end_date": null, + "newsbox_title": "News 7" + } +}, +{ + "pk": 1, + "model": "myapp.newsextended", + "fields": { + "newsbox_published": true, + "content_field": "Extra content of the news 1", + "newsbox_slug": "news-1", + "newsbox_changed_date": "2014-03-11T13:53:49.052Z", + "newsbox_creation_date": "2014-03-11T13:53:49.052Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-1", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": true, + "seo_field": "Extra SEO of the news 1", + "newsbox_summary": "Summary of the news 1", + "newsbox_meta_description": "Meta description of the news 1", + "newsbox_body": "Body of the news 1", + "newsbox_publication_end_date": null, + "newsbox_title": "News 1" + } +}, +{ + "pk": 2, + "model": "myapp.newsextended", + "fields": { + "newsbox_published": false, + "content_field": "Extra content of the news 2", + "newsbox_slug": "news-2", + "newsbox_changed_date": "2014-03-11T13:53:49.243Z", + "newsbox_creation_date": "2014-03-11T13:53:49.243Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-2", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": true, + "seo_field": "Extra SEO of the news 2", + "newsbox_summary": "Summary of the news 2", + "newsbox_meta_description": "Meta description of the news 2", + "newsbox_body": "Body of the news 2", + "newsbox_publication_end_date": null, + "newsbox_title": "News 2" + } +}, +{ + "pk": 3, + "model": "myapp.newsextended", + "fields": { + "newsbox_published": true, + "content_field": "Extra content of the news 3", + "newsbox_slug": "news-3", + "newsbox_changed_date": "2014-03-11T13:53:49.445Z", + "newsbox_creation_date": "2014-03-11T13:53:49.445Z", + "newsbox_publication_start_date": "2020-01-01T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-3", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": true, + "seo_field": "Extra SEO of the news 3", + "newsbox_summary": "Summary of the news 3", + "newsbox_meta_description": "Meta description of the news 3", + "newsbox_body": "Body of the news 3", + "newsbox_publication_end_date": null, + "newsbox_title": "News 3" + } +}, +{ + "pk": 4, + "model": "myapp.newsextended", + "fields": { + "newsbox_published": true, + "content_field": "Extra content of the news 4", + "newsbox_slug": "news-4", + "newsbox_changed_date": "2014-03-11T13:53:49.629Z", + "newsbox_creation_date": "2014-03-11T13:53:49.629Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-4", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": true, + "seo_field": "Extra SEO of the news 4", + "newsbox_summary": "Summary of the news 4", + "newsbox_meta_description": "Meta description of the news 4", + "newsbox_body": "", + "newsbox_publication_end_date": null, + "newsbox_title": "News 4" + } +}, +{ + "pk": 5, + "model": "myapp.newsextended", + "fields": { + "newsbox_published": false, + "content_field": "Extra content of the news 5", + "newsbox_slug": "news-5", + "newsbox_changed_date": "2014-03-11T13:53:49.830Z", + "newsbox_creation_date": "2014-03-11T13:53:49.830Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-5", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": true, + "seo_field": "Extra SEO of the news 5", + "newsbox_summary": "Summary of the news 5", + "newsbox_meta_description": "Meta description of the news 5", + "newsbox_body": "Body of the news 5", + "newsbox_publication_end_date": "2000-01-01T08:00:00Z", + "newsbox_title": "News 5" + } +}, +{ + "pk": 6, + "model": "myapp.newsextended", + "fields": { + "newsbox_published": true, + "content_field": "Extra content of the news 6", + "newsbox_slug": "news-6", + "newsbox_changed_date": "2014-03-11T13:53:50.016Z", + "newsbox_creation_date": "2014-03-11T13:53:50.016Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-6", + "newsbox_date": "2005-07-15T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": false, + "seo_field": "Extra SEO of the news 6", + "newsbox_summary": "Summary of the news 6", + "newsbox_meta_description": "Meta description of the news 6", + "newsbox_body": "Body of the news 6", + "newsbox_publication_end_date": null, + "newsbox_title": "News 6" + } +}, +{ + "pk": 7, + "model": "myapp.newsextended", + "fields": { + "newsbox_published": true, + "content_field": "Extra content of the news 7", + "newsbox_slug": "news-7", + "newsbox_changed_date": "2014-03-11T13:53:50.208Z", + "newsbox_creation_date": "2014-03-11T13:53:50.208Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-7", + "newsbox_date": "2020-01-01T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": true, + "seo_field": "Extra SEO of the news 7", + "newsbox_summary": "Summary of the news 7", + "newsbox_meta_description": "Meta description of the news 7", + "newsbox_body": "Body of the news 7", + "newsbox_publication_end_date": null, + "newsbox_title": "News 7" + } +} +] diff --git a/tests/myapp/models.py b/tests/myapp/models.py new file mode 100644 index 0000000..eddc3fd --- /dev/null +++ b/tests/myapp/models.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +from django.db import models +from newsbox.models import NewsboxBase, NewsboxSEOBase, NewsboxExpiredBase + +class News(NewsboxBase): + class Meta: + verbose_name = 'news - Basic' + verbose_name_plural = 'news - Basic' + +class NewsSEO(NewsboxBase, NewsboxSEOBase): + class Meta: + verbose_name = 'news - SEO' + verbose_name_plural = 'news - SEO' + +class NewsExpired(NewsboxBase, NewsboxExpiredBase): + class Meta: + verbose_name = 'news - Expirable' + verbose_name_plural = 'news - Expirable' + +class NewsComplete(NewsboxBase, NewsboxSEOBase, NewsboxExpiredBase): + class Meta: + verbose_name = 'news - Complete' + verbose_name_plural = 'news - Complete' + +class NewsExtended(NewsboxBase, NewsboxSEOBase, NewsboxExpiredBase): + general_field = models.CharField(max_length=50) + content_field = models.CharField(max_length=50) + seo_field = models.CharField(max_length=50) + + class Meta: + verbose_name = 'news - Extended' + verbose_name_plural = 'news - Extended' diff --git a/tests/myapp/tests.py b/tests/myapp/tests.py new file mode 100644 index 0000000..e9ca013 --- /dev/null +++ b/tests/myapp/tests.py @@ -0,0 +1,174 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +from django.test import TestCase, Client +from django.core.paginator import EmptyPage +from bs4 import BeautifulSoup +from .models import News, NewsSEO, NewsExpired, NewsComplete, NewsExtended + + +class NewsboxAbstractModelsTests(TestCase): + + fixtures = ['tests_data.json',] + + def test_01_manager_published(self): + """ + Test if we only get really published news via the manager + """ + newsClasses = [ + News, NewsSEO, NewsExpired, NewsComplete, NewsExtended, + ] + for cls in newsClasses: + returned_ids = list(cls.objects.published().values_list( + 'id', flat=True).order_by('id')) + self.assertEqual( + (cls.__name__,returned_ids), + (cls.__name__,[1, 4, 6, 7,])) + + def test_02_view_archive_200(self): + """ + Test if generic archive view return right informations. + """ + c = Client() + r = c.get('/news/') + + self.assertEqual(r.status_code, 200) + self.assertIn('newsset', r.context) + self.assertEqual(r.context['newsset'][0].pk, 7) + self.assertEqual(r.context['newsset'].number, 1) + self.assertEqual(r.context['newsset'].paginator.num_pages, 4) + self.assertFalse(r.context['newsset'].has_previous()) + self.assertTrue(r.context['newsset'].has_next()) + self.assertRaises(EmptyPage, r.context['newsset'].previous_page_number) + self.assertEqual(r.context['newsset'].next_page_number(), 2) + + + def test_03_view_year_archive_200(self): + """ + Test if generic year views return right informations. + """ + c = Client() + r = c.get('/news/2005/') + self.assertEqual(r.status_code, 200) + self.assertEqual(r.context['newsset'][0].pk, 6) + self.assertFalse(r.context['with_pager']) + r = c.get('/news/2014/') + self.assertEqual(r.status_code, 200) + self.assertEqual(r.context['newsset'].paginator.num_pages, 2) + r = c.get('/news/2020/') + self.assertEqual(r.status_code, 200) + self.assertEqual(r.context['newsset'].paginator.num_pages, 1) + + def test_04_view_year_archive_404(self): + """ + Test if generic year views return a 404 with an URL with a year without + any news. + """ + c = Client() + r = c.get('/newsbox/myapp/news/1985/') + self.assertEqual(r.status_code, 404) + + def test_05_view_month_archive_200(self): + """ + Test if generic month views return right informations. + """ + c = Client() + r = c.get('/newsbox/myapp/news/2005/07/') + self.assertEqual(r.status_code, 200) + ref = c.get('/newsbox/myapp/news/2005/') + self.assertEqual(r.content, ref.content) + + def test_06_view_month_archive_404(self): + """ + Test if generic month views return a 404 with an URL with a year + month + without any news. + """ + c = Client() + r = c.get('/newsbox/myapp/news/1985/07/') + self.assertEqual(r.status_code, 404) + + def test_07_view_day_archive_200(self): + """ + Test if generic day views return right informations. + """ + c = Client() + r = c.get('/newsbox/myapp/news/2005/07/15/') + self.assertEqual(r.status_code, 200) + ref = c.get('/newsbox/myapp/news/2005/07/') + self.assertEqual(r.content, ref.content) + + def test_08_view_month_archive_404(self): + """ + Test if generic day views return a 404 with an URL with a date without + any news. + """ + c = Client() + r = c.get('/newsbox/myapp/news/1985/07/02/') + self.assertEqual(r.status_code, 404) + + def test_09_view_detail_200(self): + """ + Test if generic day views return right informations. + """ + c = Client() + r = c.get('/newsbox/myapp/news/2005/07/15/news-6/') + self.assertEqual(r.status_code, 200) + self.assertEqual(r.context['news'].pk, 6) + + def test_10_view_detail_404(self): + """ + Test if generic day views return a 404 with an URL with a date without + any news. + """ + c = Client() + r = c.get('/newsbox/myapp/news/1985/07/02/my-birthday/') + self.assertEqual(r.status_code, 404) + + def test_11_view_detail_404_not_published(self): + """ + Test if generic day views return a 404 with an URL with a not published + news + """ + c = Client() + r = c.get('/newsbox/myapp/news/2014/02/22/news-2/') + self.assertEqual(r.status_code, 404) + + def has_readmore_link(self, news): + readmore_p = news.find('p', class_='readmore') + if readmore_p: + readmore_a = readmore_p.find('a') + if readmore_a: + return True + + return False + + def get_news_in_list_by_summary(self, response, summary): + soup = BeautifulSoup(response.content) + for news in soup.find_all('div', class_='news'): + readmore_summary = news.find('p', text=summary) + if readmore_summary: + return news + return None + + def test_news_4_has_no_readmore_link(self): + """ + Test if readmore link is not present in news 4 + """ + c = Client() + r = c.get('/news/?page=2') + news = self.get_news_in_list_by_summary(r, u'Summary of the news 4') + self.assertIsNotNone(news) + + found = self.has_readmore_link(news) + self.assertFalse(found) + + def test_news_6_has_readmore_link(self): + """ + Test if readmore link is present in news 6 + """ + c = Client() + r = c.get('/news/2005/') + news = self.get_news_in_list_by_summary(r, u'Summary of the news 6') + self.assertIsNotNone(news) + + found = self.has_readmore_link(news) + self.assertTrue(found) diff --git a/tests/myapp/urls.py b/tests/myapp/urls.py new file mode 100644 index 0000000..ddb3e69 --- /dev/null +++ b/tests/myapp/urls.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.conf.urls import url, include, patterns +from django.contrib import admin +from django.conf import settings +from newsbox.views import NewsboxYearArchiveView, NewsboxArchiveView + +from .models import News + +admin.autodiscover() + +urlpatterns = patterns('', + url(r'^admin/', include(admin.site.urls)), + url(r'^', include('newsbox.urls')), + url(r'^news/$', + NewsboxArchiveView.as_view(model=News, paginate_by=1), + name='news_list',), + url(r'^news/(?P<year>\d{4})/$', + NewsboxYearArchiveView.as_view(model=News, paginate_by=1), + name='news_list_y',), +) diff --git a/tests/myapp_all/__init__.py b/tests/myapp_all/__init__.py new file mode 100644 index 0000000..40a96af --- /dev/null +++ b/tests/myapp_all/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/tests/myapp_all/admin.py b/tests/myapp_all/admin.py new file mode 100644 index 0000000..95ff7bb --- /dev/null +++ b/tests/myapp_all/admin.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- + +from __future__ import unicode_literals + +from django.contrib import admin +from newsbox_cms.admin import NewsboxCMSAdmin +from newsbox.admin import NewsboxSEOAdmin, NewsboxExpiredAdmin +from newsbox_hvad.admin import NewsboxHVADAdmin + +from .models import News, NewsComplete, NewsExtended + +class NewsAdmin(NewsboxHVADAdmin, NewsboxCMSAdmin): + pass + +admin.site.register(News, NewsAdmin) + + +class NewsCompleteAdmin(NewsboxHVADAdmin, NewsboxCMSAdmin, NewsboxSEOAdmin, NewsboxExpiredAdmin): + pass + +admin.site.register(NewsComplete, NewsCompleteAdmin) + + +class NewsExtendedAdmin(NewsboxHVADAdmin, NewsboxCMSAdmin, NewsboxSEOAdmin, NewsboxExpiredAdmin): + def get_fieldsets(self, request, obj=None): + fieldsets = super(NewsExtendedAdmin, self).get_fieldsets(request, obj) + fieldsets[0][1]['fields'].append('general_field') + fieldsets[2][1]['fields'].append('content_field') + fieldsets[3][1]['fields'].append('seo_field') + return fieldsets + + def get_list_display(self, request): + list_display = super(NewsExtendedAdmin, self).get_list_display(request) + list_display.append('seo_field') + return list_display + +admin.site.register(NewsExtended, NewsExtendedAdmin) diff --git a/tests/myapp_all/cms_app.py b/tests/myapp_all/cms_app.py new file mode 100644 index 0000000..d25c3be --- /dev/null +++ b/tests/myapp_all/cms_app.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- + +from __future__ import unicode_literals + +from cms.app_base import CMSApp +from cms.apphook_pool import apphook_pool + +class NewsApphook(CMSApp): + name = 'News' + urls = ["myapp_all.urls_news"] + +apphook_pool.register(NewsApphook) diff --git a/tests/myapp_all/cms_plugins.py b/tests/myapp_all/cms_plugins.py new file mode 100644 index 0000000..ae20326 --- /dev/null +++ b/tests/myapp_all/cms_plugins.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- + +from __future__ import unicode_literals + +from cms.plugin_pool import plugin_pool +from newsbox_cms.cms_plugins import NewsboxPluginBase + +from .models import NewsPlugin as NewsPluginModel + + +class NewsPlugin(NewsboxPluginBase): + name = "News list ALL" # Name of the plugin + model = NewsPluginModel + +plugin_pool.register_plugin(NewsPlugin) diff --git a/tests/myapp_all/fixtures/tests_data.json b/tests/myapp_all/fixtures/tests_data.json new file mode 100644 index 0000000..d81809e --- /dev/null +++ b/tests/myapp_all/fixtures/tests_data.json @@ -0,0 +1,835 @@ +[ +{ + "pk": 1, + "model": "myapp_all.newstranslation", + "fields": { + "language_code": "en", + "master": 1, + "newsbox_slug": "news-1", + "newsbox_title": "News 1", + "newsbox_summary": "<p>Summary of the news 1</p>" + } +}, +{ + "pk": 2, + "model": "myapp_all.newstranslation", + "fields": { + "language_code": "fr", + "master": 1, + "newsbox_slug": "actualite-1", + "newsbox_title": "Actualit\u00e9 1", + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 1</p>" + } +}, +{ + "pk": 3, + "model": "myapp_all.newstranslation", + "fields": { + "language_code": "en", + "master": 2, + "newsbox_slug": "news-2", + "newsbox_title": "News 2", + "newsbox_summary": "<p>Summary of the news 2</p>" + } +}, +{ + "pk": 4, + "model": "myapp_all.newstranslation", + "fields": { + "language_code": "fr", + "master": 2, + "newsbox_slug": "actualite-2", + "newsbox_title": "Actualit\u00e9 2", + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 2</p>" + } +}, +{ + "pk": 5, + "model": "myapp_all.newstranslation", + "fields": { + "language_code": "en", + "master": 3, + "newsbox_slug": "news-3", + "newsbox_title": "News 3", + "newsbox_summary": "<p>Summary of the news 3</p>" + } +}, +{ + "pk": 6, + "model": "myapp_all.newstranslation", + "fields": { + "language_code": "fr", + "master": 3, + "newsbox_slug": "actualite-3", + "newsbox_title": "Actualit\u00e9 3", + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 3</p>" + } +}, +{ + "pk": 7, + "model": "myapp_all.newstranslation", + "fields": { + "language_code": "en", + "master": 4, + "newsbox_slug": "news-4", + "newsbox_title": "News 4", + "newsbox_summary": "<p>Summary of the news 4</p>" + } +}, +{ + "pk": 8, + "model": "myapp_all.newstranslation", + "fields": { + "language_code": "fr", + "master": 4, + "newsbox_slug": "actualite-4", + "newsbox_title": "Actualit\u00e9 4", + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 4</p>" + } +}, +{ + "pk": 9, + "model": "myapp_all.newstranslation", + "fields": { + "language_code": "en", + "master": 5, + "newsbox_slug": "news-5", + "newsbox_title": "News 5", + "newsbox_summary": "<p>Summary of the news 5</p>" + } +}, +{ + "pk": 10, + "model": "myapp_all.newstranslation", + "fields": { + "language_code": "fr", + "master": 5, + "newsbox_slug": "actualite-5", + "newsbox_title": "Actualit\u00e9 5", + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 5</p>" + } +}, +{ + "pk": 11, + "model": "myapp_all.newstranslation", + "fields": { + "language_code": "en", + "master": 6, + "newsbox_slug": "news-6", + "newsbox_title": "News 6", + "newsbox_summary": "<p>Summary of the news 6</p>" + } +}, +{ + "pk": 12, + "model": "myapp_all.newstranslation", + "fields": { + "language_code": "fr", + "master": 6, + "newsbox_slug": "actualite-6", + "newsbox_title": "Actualit\u00e9 6", + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 6</p>" + } +}, +{ + "pk": 13, + "model": "myapp_all.newstranslation", + "fields": { + "language_code": "en", + "master": 7, + "newsbox_slug": "news-7", + "newsbox_title": "News 7", + "newsbox_summary": "<p>Summary of the news 7</p>" + } +}, +{ + "pk": 14, + "model": "myapp_all.newstranslation", + "fields": { + "language_code": "fr", + "master": 7, + "newsbox_slug": "actualite-7", + "newsbox_title": "Actualit\u00e9 7", + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 7</p>" + } +}, +{ + "pk": 1, + "model": "myapp_all.news", + "fields": { + "newsbox_published": true, + "newsbox_creation_date": "2014-03-29T14:22:26.190Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_body": 24, + "newsbox_changed_date": "2014-03-29T14:22:26.717Z" + } +}, +{ + "pk": 2, + "model": "myapp_all.news", + "fields": { + "newsbox_published": false, + "newsbox_creation_date": "2014-03-29T14:22:27.254Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_body": 27, + "newsbox_changed_date": "2014-03-29T14:22:27.782Z" + } +}, +{ + "pk": 3, + "model": "myapp_all.news", + "fields": { + "newsbox_published": true, + "newsbox_creation_date": "2014-03-29T14:22:28.279Z", + "newsbox_publication_start_date": "2020-01-01T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_body": 30, + "newsbox_changed_date": "2014-03-29T14:22:28.907Z" + } +}, +{ + "pk": 4, + "model": "myapp_all.news", + "fields": { + "newsbox_published": true, + "newsbox_creation_date": "2014-03-29T14:22:29.718Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_body": 33, + "newsbox_changed_date": "2014-03-29T14:22:30.273Z" + } +}, +{ + "pk": 5, + "model": "myapp_all.news", + "fields": { + "newsbox_published": false, + "newsbox_creation_date": "2014-03-29T14:22:30.760Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_body": 36, + "newsbox_changed_date": "2014-03-29T14:22:31.355Z" + } +}, +{ + "pk": 6, + "model": "myapp_all.news", + "fields": { + "newsbox_published": true, + "newsbox_creation_date": "2014-03-29T14:22:31.842Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2005-07-15T08:00:00Z", + "newsbox_body": 39, + "newsbox_changed_date": "2014-03-29T14:22:32.397Z" + } +}, +{ + "pk": 7, + "model": "myapp_all.news", + "fields": { + "newsbox_published": true, + "newsbox_creation_date": "2014-03-29T14:22:32.892Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2020-01-01T08:00:00Z", + "newsbox_body": 42, + "newsbox_changed_date": "2014-03-29T14:22:33.428Z" + } +}, +{ + "pk": 1, + "model": "myapp_all.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-1", + "newsbox_slug": "news-1", + "newsbox_meta_description": "Meta description of the news 1", + "master": 1, + "newsbox_summary": "<p>Summary of the news 1</p>", + "language_code": "en", + "newsbox_title": "News 1" + } +}, +{ + "pk": 2, + "model": "myapp_all.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-1", + "newsbox_slug": "actualite-1", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 1", + "master": 1, + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 1</p>", + "language_code": "fr", + "newsbox_title": "Actualit\u00e9 1" + } +}, +{ + "pk": 3, + "model": "myapp_all.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-2", + "newsbox_slug": "news-2", + "newsbox_meta_description": "Meta description of the news 2", + "master": 2, + "newsbox_summary": "<p>Summary of the news 2</p>", + "language_code": "en", + "newsbox_title": "News 2" + } +}, +{ + "pk": 4, + "model": "myapp_all.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-2", + "newsbox_slug": "actualite-2", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 2", + "master": 2, + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 2</p>", + "language_code": "fr", + "newsbox_title": "Actualit\u00e9 2" + } +}, +{ + "pk": 5, + "model": "myapp_all.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-3", + "newsbox_slug": "news-3", + "newsbox_meta_description": "Meta description of the news 3", + "master": 3, + "newsbox_summary": "<p>Summary of the news 3</p>", + "language_code": "en", + "newsbox_title": "News 3" + } +}, +{ + "pk": 6, + "model": "myapp_all.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-3", + "newsbox_slug": "actualite-3", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 3", + "master": 3, + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 3</p>", + "language_code": "fr", + "newsbox_title": "Actualit\u00e9 3" + } +}, +{ + "pk": 7, + "model": "myapp_all.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-4", + "newsbox_slug": "news-4", + "newsbox_meta_description": "Meta description of the news 4", + "master": 4, + "newsbox_summary": "<p>Summary of the news 4</p>", + "language_code": "en", + "newsbox_title": "News 4" + } +}, +{ + "pk": 8, + "model": "myapp_all.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-4", + "newsbox_slug": "actualite-4", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 4", + "master": 4, + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 4</p>", + "language_code": "fr", + "newsbox_title": "Actualit\u00e9 4" + } +}, +{ + "pk": 9, + "model": "myapp_all.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-5", + "newsbox_slug": "news-5", + "newsbox_meta_description": "Meta description of the news 5", + "master": 5, + "newsbox_summary": "<p>Summary of the news 5</p>", + "language_code": "en", + "newsbox_title": "News 5" + } +}, +{ + "pk": 10, + "model": "myapp_all.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-5", + "newsbox_slug": "actualite-5", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 5", + "master": 5, + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 5</p>", + "language_code": "fr", + "newsbox_title": "Actualit\u00e9 5" + } +}, +{ + "pk": 11, + "model": "myapp_all.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-6", + "newsbox_slug": "news-6", + "newsbox_meta_description": "Meta description of the news 6", + "master": 6, + "newsbox_summary": "<p>Summary of the news 6</p>", + "language_code": "en", + "newsbox_title": "News 6" + } +}, +{ + "pk": 12, + "model": "myapp_all.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-6", + "newsbox_slug": "actualite-6", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 6", + "master": 6, + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 6</p>", + "language_code": "fr", + "newsbox_title": "Actualit\u00e9 6" + } +}, +{ + "pk": 13, + "model": "myapp_all.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-7", + "newsbox_slug": "news-7", + "newsbox_meta_description": "Meta description of the news 7", + "master": 7, + "newsbox_summary": "<p>Summary of the news 7</p>", + "language_code": "en", + "newsbox_title": "News 7" + } +}, +{ + "pk": 14, + "model": "myapp_all.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-7", + "newsbox_slug": "actualite-7", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 7", + "master": 7, + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 7</p>", + "language_code": "fr", + "newsbox_title": "Actualit\u00e9 7" + } +}, +{ + "pk": 1, + "model": "myapp_all.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-29T14:22:34.561Z", + "newsbox_creation_date": "2014-03-29T14:22:34.018Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_body": 45, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 2, + "model": "myapp_all.newscomplete", + "fields": { + "newsbox_published": false, + "newsbox_changed_date": "2014-03-29T14:22:35.785Z", + "newsbox_creation_date": "2014-03-29T14:22:35.132Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_body": 48, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 3, + "model": "myapp_all.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-29T14:22:36.926Z", + "newsbox_creation_date": "2014-03-29T14:22:36.389Z", + "newsbox_publication_start_date": "2020-01-01T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_body": 51, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 4, + "model": "myapp_all.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-29T14:22:38.026Z", + "newsbox_creation_date": "2014-03-29T14:22:37.480Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_body": 54, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 5, + "model": "myapp_all.newscomplete", + "fields": { + "newsbox_published": false, + "newsbox_changed_date": "2014-03-29T14:22:39.167Z", + "newsbox_creation_date": "2014-03-29T14:22:38.580Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_body": 57, + "newsbox_publication_end_date": "2000-01-01T08:00:00Z" + } +}, +{ + "pk": 6, + "model": "myapp_all.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-29T14:22:40.374Z", + "newsbox_creation_date": "2014-03-29T14:22:39.779Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2005-07-15T08:00:00Z", + "newsbox_indexed": false, + "newsbox_body": 60, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 7, + "model": "myapp_all.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-29T14:22:41.557Z", + "newsbox_creation_date": "2014-03-29T14:22:40.920Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2020-01-01T08:00:00Z", + "newsbox_indexed": true, + "newsbox_body": 63, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 1, + "model": "myapp_all.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-1", + "content_field": "Extra content of the news 1", + "newsbox_slug": "news-1", + "newsbox_meta_description": "Meta description of the news 1", + "seo_field": "Extra SEO of the news 1", + "master": 1, + "newsbox_summary": "<p>Summary of the news 1</p>", + "language_code": "en", + "newsbox_title": "News 1" + } +}, +{ + "pk": 2, + "model": "myapp_all.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-1", + "content_field": "Contenu additionnel de l'actualit\u00e9 1", + "newsbox_slug": "actualite-1", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 1", + "seo_field": "SEO additionnel de l'actualit\u00e9 1", + "master": 1, + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 1</p>", + "language_code": "fr", + "newsbox_title": "Actualit\u00e9 1" + } +}, +{ + "pk": 3, + "model": "myapp_all.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-2", + "content_field": "Extra content of the news 2", + "newsbox_slug": "news-2", + "newsbox_meta_description": "Meta description of the news 2", + "seo_field": "Extra SEO of the news 2", + "master": 2, + "newsbox_summary": "<p>Summary of the news 2</p>", + "language_code": "en", + "newsbox_title": "News 2" + } +}, +{ + "pk": 4, + "model": "myapp_all.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-2", + "content_field": "Contenu additionnel de l'actualit\u00e9 2", + "newsbox_slug": "actualite-2", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 2", + "seo_field": "SEO additionnel de l'actualit\u00e9 2", + "master": 2, + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 2</p>", + "language_code": "fr", + "newsbox_title": "Actualit\u00e9 2" + } +}, +{ + "pk": 5, + "model": "myapp_all.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-3", + "content_field": "Extra content of the news 3", + "newsbox_slug": "news-3", + "newsbox_meta_description": "Meta description of the news 3", + "seo_field": "Extra SEO of the news 3", + "master": 3, + "newsbox_summary": "<p>Summary of the news 3</p>", + "language_code": "en", + "newsbox_title": "News 3" + } +}, +{ + "pk": 6, + "model": "myapp_all.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-3", + "content_field": "Contenu additionnel de l'actualit\u00e9 3", + "newsbox_slug": "actualite-3", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 3", + "seo_field": "SEO additionnel de l'actualit\u00e9 3", + "master": 3, + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 3</p>", + "language_code": "fr", + "newsbox_title": "Actualit\u00e9 3" + } +}, +{ + "pk": 7, + "model": "myapp_all.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-4", + "content_field": "Extra content of the news 4", + "newsbox_slug": "news-4", + "newsbox_meta_description": "Meta description of the news 4", + "seo_field": "Extra SEO of the news 4", + "master": 4, + "newsbox_summary": "<p>Summary of the news 4</p>", + "language_code": "en", + "newsbox_title": "News 4" + } +}, +{ + "pk": 8, + "model": "myapp_all.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-4", + "content_field": "Contenu additionnel de l'actualit\u00e9 4", + "newsbox_slug": "actualite-4", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 4", + "seo_field": "SEO additionnel de l'actualit\u00e9 4", + "master": 4, + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 4</p>", + "language_code": "fr", + "newsbox_title": "Actualit\u00e9 4" + } +}, +{ + "pk": 9, + "model": "myapp_all.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-5", + "content_field": "Extra content of the news 5", + "newsbox_slug": "news-5", + "newsbox_meta_description": "Meta description of the news 5", + "seo_field": "Extra SEO of the news 5", + "master": 5, + "newsbox_summary": "<p>Summary of the news 5</p>", + "language_code": "en", + "newsbox_title": "News 5" + } +}, +{ + "pk": 10, + "model": "myapp_all.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-5", + "content_field": "Contenu additionnel de l'actualit\u00e9 5", + "newsbox_slug": "actualite-5", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 5", + "seo_field": "SEO additionnel de l'actualit\u00e9 5", + "master": 5, + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 5</p>", + "language_code": "fr", + "newsbox_title": "Actualit\u00e9 5" + } +}, +{ + "pk": 11, + "model": "myapp_all.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-6", + "content_field": "Extra content of the news 6", + "newsbox_slug": "news-6", + "newsbox_meta_description": "Meta description of the news 6", + "seo_field": "Extra SEO of the news 6", + "master": 6, + "newsbox_summary": "<p>Summary of the news 6</p>", + "language_code": "en", + "newsbox_title": "News 6" + } +}, +{ + "pk": 12, + "model": "myapp_all.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-6", + "content_field": "Contenu additionnel de l'actualit\u00e9 6", + "newsbox_slug": "actualite-6", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 6", + "seo_field": "SEO additionnel de l'actualit\u00e9 6", + "master": 6, + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 6</p>", + "language_code": "fr", + "newsbox_title": "Actualit\u00e9 6" + } +}, +{ + "pk": 13, + "model": "myapp_all.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-7", + "content_field": "Extra content of the news 7", + "newsbox_slug": "news-7", + "newsbox_meta_description": "Meta description of the news 7", + "seo_field": "Extra SEO of the news 7", + "master": 7, + "newsbox_summary": "<p>Summary of the news 7</p>", + "language_code": "en", + "newsbox_title": "News 7" + } +}, +{ + "pk": 14, + "model": "myapp_all.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-7", + "content_field": "Contenu additionnel de l'actualit\u00e9 7", + "newsbox_slug": "actualite-7", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 7", + "seo_field": "SEO additionnel de l'actualit\u00e9 7", + "master": 7, + "newsbox_summary": "<p>R\u00e9sum\u00e9 de l'actualit\u00e9 7</p>", + "language_code": "fr", + "newsbox_title": "Actualit\u00e9 7" + } +}, +{ + "pk": 1, + "model": "myapp_all.newsextended", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-29T14:22:18.579Z", + "newsbox_creation_date": "2014-03-29T14:22:18.020Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": true, + "newsbox_body": 3, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 2, + "model": "myapp_all.newsextended", + "fields": { + "newsbox_published": false, + "newsbox_changed_date": "2014-03-29T14:22:19.795Z", + "newsbox_creation_date": "2014-03-29T14:22:19.234Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": true, + "newsbox_body": 6, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 3, + "model": "myapp_all.newsextended", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-29T14:22:21.070Z", + "newsbox_creation_date": "2014-03-29T14:22:20.334Z", + "newsbox_publication_start_date": "2020-01-01T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": true, + "newsbox_body": 9, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 4, + "model": "myapp_all.newsextended", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-29T14:22:22.186Z", + "newsbox_creation_date": "2014-03-29T14:22:21.608Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": true, + "newsbox_body": 12, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 5, + "model": "myapp_all.newsextended", + "fields": { + "newsbox_published": false, + "newsbox_changed_date": "2014-03-29T14:22:23.352Z", + "newsbox_creation_date": "2014-03-29T14:22:22.748Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": true, + "newsbox_body": 15, + "newsbox_publication_end_date": "2000-01-01T08:00:00Z" + } +}, +{ + "pk": 6, + "model": "myapp_all.newsextended", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-29T14:22:24.476Z", + "newsbox_creation_date": "2014-03-29T14:22:23.922Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2005-07-15T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": false, + "newsbox_body": 18, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 7, + "model": "myapp_all.newsextended", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-29T14:22:25.617Z", + "newsbox_creation_date": "2014-03-29T14:22:25.055Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2020-01-01T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": true, + "newsbox_body": 21, + "newsbox_publication_end_date": null + } +} +] diff --git a/tests/myapp_all/models.py b/tests/myapp_all/models.py new file mode 100644 index 0000000..dc25caa --- /dev/null +++ b/tests/myapp_all/models.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models +from newsbox.models import NewsboxBase, NewsboxSEOBase, NewsboxExpiredBase +from newsbox_cms.models import NewsboxCMSBase, NewsboxPluginBase +from newsbox_hvad.models import NewsboxHVADBase + +class News(NewsboxHVADBase, NewsboxBase, NewsboxCMSBase): + class Meta: + verbose_name = 'news - HVADCMS' + verbose_name_plural = 'news - HVADCMS' + newsbox_detail_url_name = 'news_detail' + +class NewsComplete(NewsboxHVADBase, NewsboxBase, NewsboxCMSBase, NewsboxSEOBase, NewsboxExpiredBase): + class Meta: + verbose_name = 'news - CompleteHVADCMS' + verbose_name_plural = 'news - CompleteHVADCMS' + newsbox_detail_url_name = 'newscomplete_detail' + +class NewsExtended(NewsboxHVADBase, NewsboxBase, NewsboxCMSBase, NewsboxSEOBase, NewsboxExpiredBase): + general_field = models.CharField(max_length=50) + content_field = models.CharField(max_length=50) + seo_field = models.CharField(max_length=50) + + class Meta: + verbose_name = 'news - ExtendedHVADCMS' + verbose_name_plural = 'news - ExtendedHVADCMS' + newsbox_trans_fieldnames = ['content_field', 'seo_field'] + newsbox_detail_url_name = 'newsextended_detail' + + + +class NewsPlugin(NewsboxPluginBase): + newsbox_model = News + diff --git a/tests/myapp_all/templates/base.html b/tests/myapp_all/templates/base.html new file mode 100644 index 0000000..914218d --- /dev/null +++ b/tests/myapp_all/templates/base.html @@ -0,0 +1,13 @@ +{% load cms_tags sekizai_tags %} +<html> + <head> + {% render_block "css" %} + </head> + <body> + {% cms_toolbar %} + <div style="margin-top:200px;"> + {% block main %}{% endblock %} + </div> + {% render_block "js" %} + </body> +</html> diff --git a/tests/myapp_all/templates/list-cms.html b/tests/myapp_all/templates/list-cms.html new file mode 100644 index 0000000..726433c --- /dev/null +++ b/tests/myapp_all/templates/list-cms.html @@ -0,0 +1 @@ +{% extends "newsbox/list-cms.html" %} diff --git a/tests/myapp_all/templates/page.html b/tests/myapp_all/templates/page.html new file mode 100644 index 0000000..4ed33ca --- /dev/null +++ b/tests/myapp_all/templates/page.html @@ -0,0 +1,6 @@ +{% extends "base.html" %} +{% load cms_tags %} + +{% block main %} + {% placeholder main %} +{% endblock %} diff --git a/tests/myapp_all/tests.py b/tests/myapp_all/tests.py new file mode 100644 index 0000000..06a2feb --- /dev/null +++ b/tests/myapp_all/tests.py @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +from copy import copy + +from django.test import TestCase, Client +from django.contrib.auth.models import User +from django.core.paginator import EmptyPage +from django.utils.translation import activate +from cms.test_utils.testcases import CMSTestCase +from cms.plugin_rendering import render_plugin +from cms.api import create_page, add_plugin, publish_page, create_title +from djangocms_text_ckeditor.fields import HTMLField + +from .models import News, NewsComplete, NewsExtended, NewsPlugin as NewsPluginModel +from .cms_plugins import NewsPlugin + + +class NewsboxAbstractModelsTests(TestCase): + + fixtures = ['tests_data.json',] + + + def test_01_manager_published(self): + """ + Test if we only get really published news via the manager + """ + newsClasses = [ + News, NewsComplete, NewsExtended, + ] + for cls in newsClasses: + returned_ids = list(cls.objects.published().values_list( + 'id', flat=True).order_by('id')) + self.assertEqual( + (cls.__name__,returned_ids), + (cls.__name__,[1, 4, 6, 7,])) + + def test_02_summary_as_html_field(self): + """ + Test if newsbox_summary field is HTMLField + """ + newsClasses = [ + News, NewsComplete, NewsExtended, + ] + + for cls in newsClasses: + try: + transmodel = cls.translations.related.model + summary_field = transmodel._meta.get_field('newsbox_summary') + except: + self.fail('%s is not properly configured' % cls) + self.assertIsInstance(summary_field,HTMLField) + + +class NewsboxPageIntegrationTests(CMSTestCase): + + fixtures = ['tests_data.json',] + + def setUp(self): + self.super_user = User(username="test", is_staff=True, is_active=True, is_superuser=True) + self.super_user.set_password("test") + self.super_user.save() + + home = create_page(title='Home', slug='home', + template='page.html', + language='en', published=True, + reverse_id='home', in_navigation=True) + + create_title('fr', 'Accueil', home, slug='accueil') + home.publish('en') + home.publish('fr') + + self.page = create_page(title='News page', slug='news-page', + template='page.html', parent=home, + language='en', published=True, apphook='NewsApphook', + reverse_id='newspage', in_navigation=True) + create_title('fr', 'page Actualités', self.page, slug='page-actualites') + self.placeholder = self.page.placeholders.get(slot='main') + + self.plugin_en = add_plugin( + self.placeholder, 'NewsPlugin', 'en', + title = 'News', + numitems = 1, + with_pager = True, + page_link = None,) + self.plugin_en.save() + + self.plugin_fr = add_plugin( + self.placeholder, 'NewsPlugin', 'fr', + title = 'Actualités', + numitems = 1, + with_pager = True, + page_link = None,) + self.plugin_fr.save() + + self.page.publish('en') + self.page.publish('fr') + self.page.reload() + + self.newsPlugin = NewsPlugin() + self.placeholder = self.page.placeholders.get(slot='main') + + def test_01_cmsplugin_context(self): + expected_results = {'en':'News 7', 'fr':'Actualité 7',} + for lang in expected_results: + activate(lang) + context = self.get_context( + self.page.get_absolute_url(), page=self.page) + self.newsPlugin.render( + context, + getattr(self, 'plugin_%s' % lang), + self.placeholder) + self.assertIn('newsset', context) + self.assertEqual(context['newsset'][0].pk, 7) + self.assertEqual( + context['newsset'][0].newsbox_title, + expected_results[lang]) + self.assertEqual(context['newsset'].number, 1) + self.assertEqual(context['newsset'].paginator.num_pages, 4) + self.assertFalse(context['newsset'].has_previous()) + self.assertTrue(context['newsset'].has_next()) + self.assertRaises(EmptyPage, context['newsset'].previous_page_number) + self.assertEqual(context['newsset'].next_page_number(), 2) + + def test_02_wrong_language_404(self): + c = Client() + r_en = c.get('/en/news-page/2020/01/01/news-7/') + r_fr = c.get('/fr/page-actualites/2020/01/01/actualite-7/') + r_en_and_fr = c.get('/en/news-page/2020/01/01/actualite-7/') + self.assertEqual(r_en.status_code, 200) + self.assertEqual(r_fr.status_code, 200) + self.assertEqual(r_en_and_fr.status_code, 404) + + def test_03_get_absolute_url(self): + news7 = News.objects.get(pk=7) + expected_results = { + 'en':'/en/news-page/2020/01/01/news-7/', + 'fr':'/fr/page-actualites/2020/01/01/actualite-7/',} + for lang in expected_results: + activate(lang) + self.assertEqual(news7.get_absolute_url(), expected_results[lang]) diff --git a/tests/myapp_all/urls.py b/tests/myapp_all/urls.py new file mode 100644 index 0000000..1753ed9 --- /dev/null +++ b/tests/myapp_all/urls.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.conf.urls import url, include +from django.conf.urls.i18n import i18n_patterns +from django.contrib import admin +from django.conf import settings + +admin.autodiscover() + +urlpatterns = i18n_patterns('', + url(r'^admin/', include(admin.site.urls)), + url(r'', include('cms.urls')), +) diff --git a/tests/myapp_all/urls_news.py b/tests/myapp_all/urls_news.py new file mode 100644 index 0000000..9cdc952 --- /dev/null +++ b/tests/myapp_all/urls_news.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- + +from __future__ import unicode_literals + +from django.conf.urls import patterns, url +from newsbox_hvad.views import NewsboxHVADDetailView + +from .models import News + +urlpatterns = patterns( + '', + url( + r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/(?P<slug>[0-9a-zA-Z_-]+)/$', + NewsboxHVADDetailView.as_view(model=News,), + name='news_detail'), +) diff --git a/tests/myapp_cms/__init__.py b/tests/myapp_cms/__init__.py new file mode 100644 index 0000000..40a96af --- /dev/null +++ b/tests/myapp_cms/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/tests/myapp_cms/admin.py b/tests/myapp_cms/admin.py new file mode 100644 index 0000000..05fbf1c --- /dev/null +++ b/tests/myapp_cms/admin.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.contrib import admin +from newsbox_cms.admin import NewsboxCMSAdmin +from newsbox.admin import NewsboxSEOAdmin, NewsboxExpiredAdmin + +from .models import News, NewsComplete, NewsExtended + +class NewsAdmin(NewsboxCMSAdmin): + pass + +admin.site.register(News, NewsAdmin) + + +class NewsCompleteAdmin(NewsboxCMSAdmin, NewsboxSEOAdmin, NewsboxExpiredAdmin): + pass + +admin.site.register(NewsComplete, NewsCompleteAdmin) + + +class NewsExtendedAdmin(NewsboxCMSAdmin, NewsboxSEOAdmin, NewsboxExpiredAdmin): + def get_fieldsets(self, request, obj=None): + fieldsets = super(NewsExtendedAdmin, self).get_fieldsets(request, obj) + fieldsets[0][1]['fields'].append('general_field') + fieldsets[2][1]['fields'].append('content_field') + fieldsets[3][1]['fields'].append('seo_field') + return fieldsets + + def get_list_display(self, request): + list_display = super(NewsExtendedAdmin, self).get_list_display(request) + list_display.append('seo_field') + return list_display + +admin.site.register(NewsExtended, NewsExtendedAdmin) diff --git a/tests/myapp_cms/cms_app.py b/tests/myapp_cms/cms_app.py new file mode 100644 index 0000000..3e60259 --- /dev/null +++ b/tests/myapp_cms/cms_app.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from cms.app_base import CMSApp +from cms.apphook_pool import apphook_pool + +class NewsApphook(CMSApp): + name = 'News' + urls = ["myapp_cms.urls_news"] + +apphook_pool.register(NewsApphook) diff --git a/tests/myapp_cms/cms_plugins.py b/tests/myapp_cms/cms_plugins.py new file mode 100644 index 0000000..3581717 --- /dev/null +++ b/tests/myapp_cms/cms_plugins.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from cms.plugin_pool import plugin_pool +from newsbox_cms.cms_plugins import NewsboxPluginBase + +from .models import NewsPlugin as NewsPluginModel + + +class NewsPlugin(NewsboxPluginBase): + model = NewsPluginModel + +plugin_pool.register_plugin(NewsPlugin) diff --git a/tests/myapp_cms/fixtures/tests_data.json b/tests/myapp_cms/fixtures/tests_data.json new file mode 100644 index 0000000..ef09733 --- /dev/null +++ b/tests/myapp_cms/fixtures/tests_data.json @@ -0,0 +1,394 @@ +[ +{ + "pk": 1, + "model": "myapp_cms.news", + "fields": { + "newsbox_published": true, + "newsbox_slug": "news-1", + "newsbox_creation_date": "2014-03-11T13:53:45.196Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_summary": "<p>Summary of the news 1</p>", + "newsbox_body": 16, + "newsbox_changed_date": "2014-03-11T13:53:45.196Z", + "newsbox_title": "News 1" + } +}, +{ + "pk": 2, + "model": "myapp_cms.news", + "fields": { + "newsbox_published": false, + "newsbox_slug": "news-2", + "newsbox_creation_date": "2014-03-11T13:53:45.799Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_summary": "<p>Summary of the news 2</p>", + "newsbox_body": 18, + "newsbox_changed_date": "2014-03-11T13:53:45.799Z", + "newsbox_title": "News 2" + } +}, +{ + "pk": 3, + "model": "myapp_cms.news", + "fields": { + "newsbox_published": true, + "newsbox_slug": "news-3", + "newsbox_creation_date": "2014-03-11T13:53:46.402Z", + "newsbox_publication_start_date": "2020-01-01T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_summary": "<p>Summary of the news 3</p>", + "newsbox_body": 20, + "newsbox_changed_date": "2014-03-11T13:53:46.402Z", + "newsbox_title": "News 3" + } +}, +{ + "pk": 4, + "model": "myapp_cms.news", + "fields": { + "newsbox_published": true, + "newsbox_slug": "news-4", + "newsbox_creation_date": "2014-03-11T13:53:47.013Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_summary": "<p>Summary of the news 4</p>", + "newsbox_body": 22, + "newsbox_changed_date": "2014-03-11T13:53:47.013Z", + "newsbox_title": "News 4" + } +}, +{ + "pk": 5, + "model": "myapp_cms.news", + "fields": { + "newsbox_published": false, + "newsbox_slug": "news-5", + "newsbox_creation_date": "2014-03-11T13:53:47.618Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_summary": "<p>Summary of the news 5</p>", + "newsbox_body": 24, + "newsbox_changed_date": "2014-03-11T13:53:47.618Z", + "newsbox_title": "News 5" + } +}, +{ + "pk": 6, + "model": "myapp_cms.news", + "fields": { + "newsbox_published": true, + "newsbox_slug": "news-6", + "newsbox_creation_date": "2014-03-11T13:53:48.237Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2005-07-15T08:00:00Z", + "newsbox_summary": "<p>Summary of the news 6</p>", + "newsbox_body": 26, + "newsbox_changed_date": "2014-03-11T13:53:48.237Z", + "newsbox_title": "News 6" + } +}, +{ + "pk": 7, + "model": "myapp_cms.news", + "fields": { + "newsbox_published": true, + "newsbox_slug": "news-7", + "newsbox_creation_date": "2014-03-11T13:53:48.840Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2020-01-01T08:00:00Z", + "newsbox_summary": "<p>Summary of the news 7</p>", + "newsbox_body": 28, + "newsbox_changed_date": "2014-03-11T13:53:48.840Z", + "newsbox_title": "News 7" + } +}, +{ + "pk": 1, + "model": "myapp_cms.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_meta_description": "Meta description of the news 1", + "newsbox_slug": "news-1", + "newsbox_changed_date": "2014-03-11T13:53:52.178Z", + "newsbox_creation_date": "2014-03-11T13:53:52.178Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-1", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_summary": "<p>Summary of the news 1</p>", + "newsbox_body": 30, + "newsbox_publication_end_date": null, + "newsbox_title": "News 1" + } +}, +{ + "pk": 2, + "model": "myapp_cms.newscomplete", + "fields": { + "newsbox_published": false, + "newsbox_meta_description": "Meta description of the news 2", + "newsbox_slug": "news-2", + "newsbox_changed_date": "2014-03-11T13:53:52.797Z", + "newsbox_creation_date": "2014-03-11T13:53:52.797Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-2", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_summary": "<p>Summary of the news 2</p>", + "newsbox_body": 32, + "newsbox_publication_end_date": null, + "newsbox_title": "News 2" + } +}, +{ + "pk": 3, + "model": "myapp_cms.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_meta_description": "Meta description of the news 3", + "newsbox_slug": "news-3", + "newsbox_changed_date": "2014-03-11T13:53:53.426Z", + "newsbox_creation_date": "2014-03-11T13:53:53.426Z", + "newsbox_publication_start_date": "2020-01-01T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-3", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_summary": "<p>Summary of the news 3</p>", + "newsbox_body": 34, + "newsbox_publication_end_date": null, + "newsbox_title": "News 3" + } +}, +{ + "pk": 4, + "model": "myapp_cms.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_meta_description": "Meta description of the news 4", + "newsbox_slug": "news-4", + "newsbox_changed_date": "2014-03-11T13:53:54.055Z", + "newsbox_creation_date": "2014-03-11T13:53:54.055Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-4", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_summary": "<p>Summary of the news 4</p>", + "newsbox_body": 36, + "newsbox_publication_end_date": null, + "newsbox_title": "News 4" + } +}, +{ + "pk": 5, + "model": "myapp_cms.newscomplete", + "fields": { + "newsbox_published": false, + "newsbox_meta_description": "Meta description of the news 5", + "newsbox_slug": "news-5", + "newsbox_changed_date": "2014-03-11T13:53:54.674Z", + "newsbox_creation_date": "2014-03-11T13:53:54.674Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-5", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_summary": "<p>Summary of the news 5</p>", + "newsbox_body": 38, + "newsbox_publication_end_date": "2000-01-01T08:00:00Z", + "newsbox_title": "News 5" + } +}, +{ + "pk": 6, + "model": "myapp_cms.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_meta_description": "Meta description of the news 6", + "newsbox_slug": "news-6", + "newsbox_changed_date": "2014-03-11T13:53:55.303Z", + "newsbox_creation_date": "2014-03-11T13:53:55.303Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-6", + "newsbox_date": "2005-07-15T08:00:00Z", + "newsbox_indexed": false, + "newsbox_summary": "<p>Summary of the news 6</p>", + "newsbox_body": 40, + "newsbox_publication_end_date": null, + "newsbox_title": "News 6" + } +}, +{ + "pk": 7, + "model": "myapp_cms.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_meta_description": "Meta description of the news 7", + "newsbox_slug": "news-7", + "newsbox_changed_date": "2014-03-11T13:53:55.922Z", + "newsbox_creation_date": "2014-03-11T13:53:55.921Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-7", + "newsbox_date": "2020-01-01T08:00:00Z", + "newsbox_indexed": true, + "newsbox_summary": "<p>Summary of the news 7</p>", + "newsbox_body": 42, + "newsbox_publication_end_date": null, + "newsbox_title": "News 7" + } +}, +{ + "pk": 1, + "model": "myapp_cms.newsextended", + "fields": { + "newsbox_published": true, + "content_field": "", + "newsbox_slug": "news-1", + "newsbox_changed_date": "2014-03-11T13:53:40.980Z", + "newsbox_creation_date": "2014-03-11T13:53:40.980Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-1", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "", + "newsbox_indexed": true, + "seo_field": "", + "newsbox_summary": "<p>Summary of the news 1</p>", + "newsbox_meta_description": "Meta description of the news 1", + "newsbox_body": 2, + "newsbox_publication_end_date": null, + "newsbox_title": "News 1" + } +}, +{ + "pk": 2, + "model": "myapp_cms.newsextended", + "fields": { + "newsbox_published": false, + "content_field": "", + "newsbox_slug": "news-2", + "newsbox_changed_date": "2014-03-11T13:53:41.585Z", + "newsbox_creation_date": "2014-03-11T13:53:41.585Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-2", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "", + "newsbox_indexed": true, + "seo_field": "", + "newsbox_summary": "<p>Summary of the news 2</p>", + "newsbox_meta_description": "Meta description of the news 2", + "newsbox_body": 4, + "newsbox_publication_end_date": null, + "newsbox_title": "News 2" + } +}, +{ + "pk": 3, + "model": "myapp_cms.newsextended", + "fields": { + "newsbox_published": true, + "content_field": "", + "newsbox_slug": "news-3", + "newsbox_changed_date": "2014-03-11T13:53:42.180Z", + "newsbox_creation_date": "2014-03-11T13:53:42.180Z", + "newsbox_publication_start_date": "2020-01-01T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-3", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "", + "newsbox_indexed": true, + "seo_field": "", + "newsbox_summary": "<p>Summary of the news 3</p>", + "newsbox_meta_description": "Meta description of the news 3", + "newsbox_body": 6, + "newsbox_publication_end_date": null, + "newsbox_title": "News 3" + } +}, +{ + "pk": 4, + "model": "myapp_cms.newsextended", + "fields": { + "newsbox_published": true, + "content_field": "", + "newsbox_slug": "news-4", + "newsbox_changed_date": "2014-03-11T13:53:42.785Z", + "newsbox_creation_date": "2014-03-11T13:53:42.784Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-4", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "", + "newsbox_indexed": true, + "seo_field": "", + "newsbox_summary": "<p>Summary of the news 4</p>", + "newsbox_meta_description": "Meta description of the news 4", + "newsbox_body": 8, + "newsbox_publication_end_date": null, + "newsbox_title": "News 4" + } +}, +{ + "pk": 5, + "model": "myapp_cms.newsextended", + "fields": { + "newsbox_published": false, + "content_field": "", + "newsbox_slug": "news-5", + "newsbox_changed_date": "2014-03-11T13:53:43.377Z", + "newsbox_creation_date": "2014-03-11T13:53:43.377Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-5", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "", + "newsbox_indexed": true, + "seo_field": "", + "newsbox_summary": "<p>Summary of the news 5</p>", + "newsbox_meta_description": "Meta description of the news 5", + "newsbox_body": 10, + "newsbox_publication_end_date": "2000-01-01T08:00:00Z", + "newsbox_title": "News 5" + } +}, +{ + "pk": 6, + "model": "myapp_cms.newsextended", + "fields": { + "newsbox_published": true, + "content_field": "", + "newsbox_slug": "news-6", + "newsbox_changed_date": "2014-03-11T13:53:43.980Z", + "newsbox_creation_date": "2014-03-11T13:53:43.980Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-6", + "newsbox_date": "2005-07-15T08:00:00Z", + "general_field": "", + "newsbox_indexed": false, + "seo_field": "", + "newsbox_summary": "<p>Summary of the news 6</p>", + "newsbox_meta_description": "Meta description of the news 6", + "newsbox_body": 12, + "newsbox_publication_end_date": null, + "newsbox_title": "News 6" + } +}, +{ + "pk": 7, + "model": "myapp_cms.newsextended", + "fields": { + "newsbox_published": true, + "content_field": "", + "newsbox_slug": "news-7", + "newsbox_changed_date": "2014-03-11T13:53:44.583Z", + "newsbox_creation_date": "2014-03-11T13:53:44.583Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_meta_keywords": "keyword1, keyword2, news-7", + "newsbox_date": "2020-01-01T08:00:00Z", + "general_field": "", + "newsbox_indexed": true, + "seo_field": "", + "newsbox_summary": "<p>Summary of the news 7</p>", + "newsbox_meta_description": "Meta description of the news 7", + "newsbox_body": 14, + "newsbox_publication_end_date": null, + "newsbox_title": "News 7" + } +} +] diff --git a/tests/myapp_cms/models.py b/tests/myapp_cms/models.py new file mode 100644 index 0000000..16622b3 --- /dev/null +++ b/tests/myapp_cms/models.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models +from newsbox.models import NewsboxBase, NewsboxSEOBase, NewsboxExpiredBase +from newsbox_cms.models import NewsboxCMSBase, NewsboxPluginBase + +class News(NewsboxBase, NewsboxCMSBase): + class Meta: + verbose_name = 'news - CMS' + verbose_name_plural = 'news - CMS' + newsbox_detail_url_name = 'news_detail' + + +class NewsComplete(NewsboxBase, NewsboxSEOBase, NewsboxExpiredBase, NewsboxCMSBase): + class Meta: + verbose_name = 'news - CompleteCMS' + verbose_name_plural = 'news - CompleteCMS' + newsbox_detail_url_name = 'newscomplete_detail' + + +class NewsExtended(NewsboxBase, NewsboxSEOBase, NewsboxExpiredBase, NewsboxCMSBase): + general_field = models.CharField(max_length=50) + content_field = models.CharField(max_length=50) + seo_field = models.CharField(max_length=50) + + class Meta: + verbose_name = 'news - ExtendedCMS' + verbose_name_plural = 'news - ExtendedCMS' + newsbox_detail_url_name = 'newsextended_detail' + + +class NewsPlugin(NewsboxPluginBase): + newsbox_model = News + diff --git a/tests/myapp_cms/templates/base.html b/tests/myapp_cms/templates/base.html new file mode 100644 index 0000000..8e730c8 --- /dev/null +++ b/tests/myapp_cms/templates/base.html @@ -0,0 +1,13 @@ +{% load cms_tags sekizai_tags %} +<html> + <head> + {% render_block "css" %} + </head> + <body> + {% cms_toolbar %} + {% block main %} + {% placeholder main %} + {% endblock %} + {% render_block "js" %} + </body> +</html> diff --git a/tests/myapp_cms/templates/list-cms.html b/tests/myapp_cms/templates/list-cms.html new file mode 100644 index 0000000..726433c --- /dev/null +++ b/tests/myapp_cms/templates/list-cms.html @@ -0,0 +1 @@ +{% extends "newsbox/list-cms.html" %} diff --git a/tests/myapp_cms/templates/page.html b/tests/myapp_cms/templates/page.html new file mode 100644 index 0000000..4ed33ca --- /dev/null +++ b/tests/myapp_cms/templates/page.html @@ -0,0 +1,6 @@ +{% extends "base.html" %} +{% load cms_tags %} + +{% block main %} + {% placeholder main %} +{% endblock %} diff --git a/tests/myapp_cms/tests.py b/tests/myapp_cms/tests.py new file mode 100644 index 0000000..f0a5284 --- /dev/null +++ b/tests/myapp_cms/tests.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +from copy import copy + +from django.test import TestCase, Client +from django.contrib.auth.models import User +from django.core.paginator import EmptyPage +from cms.test_utils.testcases import CMSTestCase +from cms.plugin_rendering import render_plugin +from cms.api import create_page, add_plugin, publish_page +from djangocms_text_ckeditor.fields import HTMLField + +from .models import News, NewsComplete, NewsExtended, NewsPlugin as NewsPluginModel +from .cms_plugins import NewsPlugin + + +class NewsboxAbstractModelsTests(TestCase): + + fixtures = ['tests_data.json',] + + + def test_01_manager_published(self): + """ + Test if we only get really published news via the manager + """ + newsClasses = [ + News, NewsComplete, NewsExtended, + ] + for cls in newsClasses: + returned_ids = list(cls.objects.published().values_list( + 'id', flat=True).order_by('id')) + self.assertEqual( + (cls.__name__,returned_ids), + (cls.__name__,[1, 4, 6, 7,])) + + def test_02_summary_as_html_field(self): + """ + Test if newsbox_summary field is HTMLField + """ + newsClasses = [ + News, NewsComplete, NewsExtended, + ] + + for cls in newsClasses: + try: + summary_field = cls._meta.get_field('newsbox_summary') + except: + self.fail('%s is not properly configured' % cls) + self.assertIsInstance(summary_field, HTMLField) + + +class NewsboxPageIntegrationTests(CMSTestCase): + + fixtures = ['tests_data.json',] + + def setUp(self): + self.super_user = User(username="test", is_staff=True, is_active=True, is_superuser=True) + self.super_user.set_password("test") + self.super_user.save() + + home = create_page(title='Home', + template='page.html', + language='en', published=True, + reverse_id='home', in_navigation=True) + + self.page = create_page(title='News page', + template='page.html', parent=home, + language='en', published=True, apphook='NewsApphook', + reverse_id='newspage', in_navigation=True) + + self.placeholder = self.page.placeholders.get(slot='main') + self.plugin = add_plugin( + self.placeholder, 'NewsPlugin', 'en', + title = 'News', + numitems = 1, + with_pager = True, + page_link = None,) + self.plugin.save() + self.newsPlugin = NewsPlugin() + self.page = publish_page(self.page, self.super_user, 'en') + self.placeholder = self.page.placeholders.get(slot='main') + + def test_01_cmsplugin_context(self): + context = self.get_context(self.page.get_absolute_url(), page=self.page) + self.newsPlugin.render(context, self.plugin, self.placeholder) + self.assertIn('newsset', context) + self.assertEqual(context['newsset'][0].pk, 7) + self.assertEqual(context['newsset'].number, 1) + self.assertEqual(context['newsset'].paginator.num_pages, 4) + self.assertFalse(context['newsset'].has_previous()) + self.assertTrue(context['newsset'].has_next()) + self.assertRaises(EmptyPage, context['newsset'].previous_page_number) + self.assertEqual(context['newsset'].next_page_number(), 2) + + def test_02_cmsplugin_disable_pager(self): + context = self.get_context(self.page.get_absolute_url(), page=self.page) + plugin = copy(self.plugin) + plugin.with_pager = False + self.newsPlugin.render(context, plugin, self.placeholder) + self.assertIn('newsset', context) + with self.assertRaises(AttributeError): + getattr(context['newsset'], 'has_previous') + with self.assertRaises(AttributeError): + getattr(context['newsset'], 'paginator') + + def test_03_cmsplugin_numitems(self): + context = self.get_context(self.page.get_absolute_url(), page=self.page) + plugin = copy(self.plugin) + plugin.numitems = 2 + self.newsPlugin.render(context, plugin, self.placeholder) + self.assertIn('newsset', context) + self.assertEqual(context['newsset'].paginator.num_pages, 2) + + def test_04_cmsplugin_html(self): + context = self.get_context(self.page.get_absolute_url(), page=self.page) + self.newsPlugin.render(context, self.plugin, self.placeholder) + html = render_plugin( + context, + self.newsPlugin, + self.placeholder, + self.newsPlugin.render_template) + self.assertIn('<a href="/news-page/2020/01/01/news-7/">News 7</a>', html) + self.assertIn('<a class="next" href="?page=2">Next news</a>', html) + + def test_05_app_view_detail_200(self): + """ + Test if generic day views return right informations. + """ + c = Client() + r = c.get('/news-page/2005/07/15/news-6/') + self.assertEqual(r.status_code, 200) + self.assertEqual(r.context['news'].pk, 6) + + def test_06_app_view_detail_404(self): + """ + Test if generic day views return a 404 with an URL with a date without + any news. + """ + c = Client() + r = c.get('/news-page/1985/07/02/my-birthday/') + self.assertEqual(r.status_code, 404) + + def test_07_app_view_detail_404_not_published(self): + """ + Test if generic day views return a 404 with an URL with a not published + news + """ + c = Client() + r = c.get('/news-page/2014/02/22/news-2/') + self.assertEqual(r.status_code, 404) diff --git a/tests/myapp_cms/urls.py b/tests/myapp_cms/urls.py new file mode 100644 index 0000000..2a7ddb5 --- /dev/null +++ b/tests/myapp_cms/urls.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.conf.urls import url, include, patterns +from django.contrib import admin +from django.conf import settings + +admin.autodiscover() + +urlpatterns = patterns('', + url(r'^admin/', include(admin.site.urls)), + url(r'', include('cms.urls')), +) diff --git a/tests/myapp_cms/urls_news.py b/tests/myapp_cms/urls_news.py new file mode 100644 index 0000000..a9a706d --- /dev/null +++ b/tests/myapp_cms/urls_news.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.conf.urls import patterns, url +from newsbox.views import NewsboxDetailView + +from .models import News + +urlpatterns = patterns( + '', + url( + r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/(?P<slug>[0-9a-zA-Z_-]+)/$', + NewsboxDetailView.as_view( + model=News,), + name='news_detail'), +) diff --git a/tests/myapp_hvad/__init__.py b/tests/myapp_hvad/__init__.py new file mode 100644 index 0000000..40a96af --- /dev/null +++ b/tests/myapp_hvad/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/tests/myapp_hvad/fixtures/tests_data.json b/tests/myapp_hvad/fixtures/tests_data.json new file mode 100644 index 0000000..1c6ef94 --- /dev/null +++ b/tests/myapp_hvad/fixtures/tests_data.json @@ -0,0 +1,856 @@ +[ +{ + "pk": 1, + "model": "myapp_hvad.newstranslation", + "fields": { + "newsbox_slug": "news-1", + "master": 1, + "newsbox_summary": "Summary of the news 1", + "language_code": "en", + "newsbox_body": "Body of the news 1", + "newsbox_title": "News 1" + } +}, +{ + "pk": 2, + "model": "myapp_hvad.newstranslation", + "fields": { + "newsbox_slug": "actualite-1", + "master": 1, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 1", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 1", + "newsbox_title": "Actualit\u00e9 1" + } +}, +{ + "pk": 3, + "model": "myapp_hvad.newstranslation", + "fields": { + "newsbox_slug": "news-2", + "master": 2, + "newsbox_summary": "Summary of the news 2", + "language_code": "en", + "newsbox_body": "Body of the news 2", + "newsbox_title": "News 2" + } +}, +{ + "pk": 4, + "model": "myapp_hvad.newstranslation", + "fields": { + "newsbox_slug": "actualite-2", + "master": 2, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 2", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 2", + "newsbox_title": "Actualit\u00e9 2" + } +}, +{ + "pk": 5, + "model": "myapp_hvad.newstranslation", + "fields": { + "newsbox_slug": "news-3", + "master": 3, + "newsbox_summary": "Summary of the news 3", + "language_code": "en", + "newsbox_body": "Body of the news 3", + "newsbox_title": "News 3" + } +}, +{ + "pk": 6, + "model": "myapp_hvad.newstranslation", + "fields": { + "newsbox_slug": "actualite-3", + "master": 3, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 3", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 3", + "newsbox_title": "Actualit\u00e9 3" + } +}, +{ + "pk": 7, + "model": "myapp_hvad.newstranslation", + "fields": { + "newsbox_slug": "news-4", + "master": 4, + "newsbox_summary": "Summary of the news 4", + "language_code": "en", + "newsbox_body": "", + "newsbox_title": "News 4" + } +}, +{ + "pk": 8, + "model": "myapp_hvad.newstranslation", + "fields": { + "newsbox_slug": "actualite-4", + "master": 4, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 4", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 4", + "newsbox_title": "Actualit\u00e9 4" + } +}, +{ + "pk": 9, + "model": "myapp_hvad.newstranslation", + "fields": { + "newsbox_slug": "news-5", + "master": 5, + "newsbox_summary": "Summary of the news 5", + "language_code": "en", + "newsbox_body": "Body of the news 5", + "newsbox_title": "News 5" + } +}, +{ + "pk": 10, + "model": "myapp_hvad.newstranslation", + "fields": { + "newsbox_slug": "actualite-5", + "master": 5, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 5", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 5", + "newsbox_title": "Actualit\u00e9 5" + } +}, +{ + "pk": 11, + "model": "myapp_hvad.newstranslation", + "fields": { + "newsbox_slug": "news-6", + "master": 6, + "newsbox_summary": "Summary of the news 6", + "language_code": "en", + "newsbox_body": "Body of the news 6", + "newsbox_title": "News 6" + } +}, +{ + "pk": 12, + "model": "myapp_hvad.newstranslation", + "fields": { + "newsbox_slug": "actualite-6", + "master": 6, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 6", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 6", + "newsbox_title": "Actualit\u00e9 6" + } +}, +{ + "pk": 13, + "model": "myapp_hvad.newstranslation", + "fields": { + "newsbox_slug": "news-7", + "master": 7, + "newsbox_summary": "Summary of the news 7", + "language_code": "en", + "newsbox_body": "Body of the news 7", + "newsbox_title": "News 7" + } +}, +{ + "pk": 14, + "model": "myapp_hvad.newstranslation", + "fields": { + "newsbox_slug": "actualite-7", + "master": 7, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 7", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 7", + "newsbox_title": "Actualit\u00e9 7" + } +}, +{ + "pk": 1, + "model": "myapp_hvad.news", + "fields": { + "newsbox_creation_date": "2014-03-11T13:53:29.989Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_changed_date": "2014-03-11T13:53:30.366Z", + "newsbox_published": true, + "newsbox_date": "2014-02-22T08:00:00Z" + } +}, +{ + "pk": 2, + "model": "myapp_hvad.news", + "fields": { + "newsbox_creation_date": "2014-03-11T13:53:30.736Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_changed_date": "2014-03-11T13:53:31.111Z", + "newsbox_published": false, + "newsbox_date": "2014-02-22T08:00:00Z" + } +}, +{ + "pk": 3, + "model": "myapp_hvad.news", + "fields": { + "newsbox_creation_date": "2014-03-11T13:53:31.496Z", + "newsbox_publication_start_date": "2020-01-01T08:00:00Z", + "newsbox_changed_date": "2014-03-11T13:53:31.884Z", + "newsbox_published": true, + "newsbox_date": "2014-02-22T08:00:00Z" + } +}, +{ + "pk": 4, + "model": "myapp_hvad.news", + "fields": { + "newsbox_creation_date": "2014-03-11T13:53:32.261Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_changed_date": "2014-03-11T13:53:32.646Z", + "newsbox_published": true, + "newsbox_date": "2014-02-22T08:00:00Z" + } +}, +{ + "pk": 5, + "model": "myapp_hvad.news", + "fields": { + "newsbox_creation_date": "2014-03-11T13:53:33.016Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_changed_date": "2014-03-11T13:53:33.377Z", + "newsbox_published": false, + "newsbox_date": "2014-02-22T08:00:00Z" + } +}, +{ + "pk": 6, + "model": "myapp_hvad.news", + "fields": { + "newsbox_creation_date": "2014-03-11T13:53:33.752Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_changed_date": "2014-03-11T13:53:34.122Z", + "newsbox_published": true, + "newsbox_date": "2005-07-15T08:00:00Z" + } +}, +{ + "pk": 7, + "model": "myapp_hvad.news", + "fields": { + "newsbox_creation_date": "2014-03-11T13:53:34.499Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_changed_date": "2014-03-11T13:53:34.868Z", + "newsbox_published": true, + "newsbox_date": "2020-01-01T08:00:00Z" + } +}, +{ + "pk": 1, + "model": "myapp_hvad.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-1", + "newsbox_slug": "news-1", + "newsbox_meta_description": "Meta description of the news 1", + "master": 1, + "newsbox_summary": "Summary of the news 1", + "language_code": "en", + "newsbox_body": "Body of the news 1", + "newsbox_title": "News 1" + } +}, +{ + "pk": 2, + "model": "myapp_hvad.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-1", + "newsbox_slug": "actualite-1", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 1", + "master": 1, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 1", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 1", + "newsbox_title": "Actualit\u00e9 1" + } +}, +{ + "pk": 3, + "model": "myapp_hvad.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-2", + "newsbox_slug": "news-2", + "newsbox_meta_description": "Meta description of the news 2", + "master": 2, + "newsbox_summary": "Summary of the news 2", + "language_code": "en", + "newsbox_body": "Body of the news 2", + "newsbox_title": "News 2" + } +}, +{ + "pk": 4, + "model": "myapp_hvad.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-2", + "newsbox_slug": "actualite-2", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 2", + "master": 2, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 2", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 2", + "newsbox_title": "Actualit\u00e9 2" + } +}, +{ + "pk": 5, + "model": "myapp_hvad.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-3", + "newsbox_slug": "news-3", + "newsbox_meta_description": "Meta description of the news 3", + "master": 3, + "newsbox_summary": "Summary of the news 3", + "language_code": "en", + "newsbox_body": "Body of the news 3", + "newsbox_title": "News 3" + } +}, +{ + "pk": 6, + "model": "myapp_hvad.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-3", + "newsbox_slug": "actualite-3", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 3", + "master": 3, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 3", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 3", + "newsbox_title": "Actualit\u00e9 3" + } +}, +{ + "pk": 7, + "model": "myapp_hvad.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-4", + "newsbox_slug": "news-4", + "newsbox_meta_description": "Meta description of the news 4", + "master": 4, + "newsbox_summary": "Summary of the news 4", + "language_code": "en", + "newsbox_body": "", + "newsbox_title": "News 4" + } +}, +{ + "pk": 8, + "model": "myapp_hvad.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-4", + "newsbox_slug": "actualite-4", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 4", + "master": 4, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 4", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 4", + "newsbox_title": "Actualit\u00e9 4" + } +}, +{ + "pk": 9, + "model": "myapp_hvad.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-5", + "newsbox_slug": "news-5", + "newsbox_meta_description": "Meta description of the news 5", + "master": 5, + "newsbox_summary": "Summary of the news 5", + "language_code": "en", + "newsbox_body": "Body of the news 5", + "newsbox_title": "News 5" + } +}, +{ + "pk": 10, + "model": "myapp_hvad.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-5", + "newsbox_slug": "actualite-5", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 5", + "master": 5, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 5", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 5", + "newsbox_title": "Actualit\u00e9 5" + } +}, +{ + "pk": 11, + "model": "myapp_hvad.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-6", + "newsbox_slug": "news-6", + "newsbox_meta_description": "Meta description of the news 6", + "master": 6, + "newsbox_summary": "Summary of the news 6", + "language_code": "en", + "newsbox_body": "Body of the news 6", + "newsbox_title": "News 6" + } +}, +{ + "pk": 12, + "model": "myapp_hvad.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-6", + "newsbox_slug": "actualite-6", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 6", + "master": 6, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 6", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 6", + "newsbox_title": "Actualit\u00e9 6" + } +}, +{ + "pk": 13, + "model": "myapp_hvad.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-7", + "newsbox_slug": "news-7", + "newsbox_meta_description": "Meta description of the news 7", + "master": 7, + "newsbox_summary": "Summary of the news 7", + "language_code": "en", + "newsbox_body": "Body of the news 7", + "newsbox_title": "News 7" + } +}, +{ + "pk": 14, + "model": "myapp_hvad.newscompletetranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-7", + "newsbox_slug": "actualite-7", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 7", + "master": 7, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 7", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 7", + "newsbox_title": "Actualit\u00e9 7" + } +}, +{ + "pk": 1, + "model": "myapp_hvad.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-11T13:53:35.631Z", + "newsbox_creation_date": "2014-03-11T13:53:35.238Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 2, + "model": "myapp_hvad.newscomplete", + "fields": { + "newsbox_published": false, + "newsbox_changed_date": "2014-03-11T13:53:36.378Z", + "newsbox_creation_date": "2014-03-11T13:53:35.993Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 3, + "model": "myapp_hvad.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-11T13:53:37.124Z", + "newsbox_creation_date": "2014-03-11T13:53:36.747Z", + "newsbox_publication_start_date": "2020-01-01T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 4, + "model": "myapp_hvad.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-11T13:53:37.871Z", + "newsbox_creation_date": "2014-03-11T13:53:37.494Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 5, + "model": "myapp_hvad.newscomplete", + "fields": { + "newsbox_published": false, + "newsbox_changed_date": "2014-03-11T13:53:38.660Z", + "newsbox_creation_date": "2014-03-11T13:53:38.272Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "newsbox_indexed": true, + "newsbox_publication_end_date": "2000-01-01T08:00:00Z" + } +}, +{ + "pk": 6, + "model": "myapp_hvad.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-11T13:53:39.438Z", + "newsbox_creation_date": "2014-03-11T13:53:39.045Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2005-07-15T08:00:00Z", + "newsbox_indexed": false, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 7, + "model": "myapp_hvad.newscomplete", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-11T13:53:40.209Z", + "newsbox_creation_date": "2014-03-11T13:53:39.824Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2020-01-01T08:00:00Z", + "newsbox_indexed": true, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 1, + "model": "myapp_hvad.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-1", + "content_field": "Extra content of the news 1", + "newsbox_slug": "news-1", + "newsbox_meta_description": "Meta description of the news 1", + "seo_field": "Extra SEO of the news 1", + "master": 1, + "newsbox_summary": "Summary of the news 1", + "language_code": "en", + "newsbox_body": "Body of the news 1", + "newsbox_title": "News 1" + } +}, +{ + "pk": 2, + "model": "myapp_hvad.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-1", + "content_field": "Contenu additionnel de l'actualit\u00e9 1", + "newsbox_slug": "actualite-1", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 1", + "seo_field": "SEO additionnel de l'actualit\u00e9 1", + "master": 1, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 1", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 1", + "newsbox_title": "Actualit\u00e9 1" + } +}, +{ + "pk": 3, + "model": "myapp_hvad.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-2", + "content_field": "Extra content of the news 2", + "newsbox_slug": "news-2", + "newsbox_meta_description": "Meta description of the news 2", + "seo_field": "Extra SEO of the news 2", + "master": 2, + "newsbox_summary": "Summary of the news 2", + "language_code": "en", + "newsbox_body": "Body of the news 2", + "newsbox_title": "News 2" + } +}, +{ + "pk": 4, + "model": "myapp_hvad.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-2", + "content_field": "Contenu additionnel de l'actualit\u00e9 2", + "newsbox_slug": "actualite-2", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 2", + "seo_field": "SEO additionnel de l'actualit\u00e9 2", + "master": 2, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 2", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 2", + "newsbox_title": "Actualit\u00e9 2" + } +}, +{ + "pk": 5, + "model": "myapp_hvad.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-3", + "content_field": "Extra content of the news 3", + "newsbox_slug": "news-3", + "newsbox_meta_description": "Meta description of the news 3", + "seo_field": "Extra SEO of the news 3", + "master": 3, + "newsbox_summary": "Summary of the news 3", + "language_code": "en", + "newsbox_body": "Body of the news 3", + "newsbox_title": "News 3" + } +}, +{ + "pk": 6, + "model": "myapp_hvad.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-3", + "content_field": "Contenu additionnel de l'actualit\u00e9 3", + "newsbox_slug": "actualite-3", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 3", + "seo_field": "SEO additionnel de l'actualit\u00e9 3", + "master": 3, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 3", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 3", + "newsbox_title": "Actualit\u00e9 3" + } +}, +{ + "pk": 7, + "model": "myapp_hvad.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-4", + "content_field": "Extra content of the news 4", + "newsbox_slug": "news-4", + "newsbox_meta_description": "Meta description of the news 4", + "seo_field": "Extra SEO of the news 4", + "master": 4, + "newsbox_summary": "Summary of the news 4", + "language_code": "en", + "newsbox_body": "", + "newsbox_title": "News 4" + } +}, +{ + "pk": 8, + "model": "myapp_hvad.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-4", + "content_field": "Contenu additionnel de l'actualit\u00e9 4", + "newsbox_slug": "actualite-4", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 4", + "seo_field": "SEO additionnel de l'actualit\u00e9 4", + "master": 4, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 4", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 4", + "newsbox_title": "Actualit\u00e9 4" + } +}, +{ + "pk": 9, + "model": "myapp_hvad.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-5", + "content_field": "Extra content of the news 5", + "newsbox_slug": "news-5", + "newsbox_meta_description": "Meta description of the news 5", + "seo_field": "Extra SEO of the news 5", + "master": 5, + "newsbox_summary": "Summary of the news 5", + "language_code": "en", + "newsbox_body": "Body of the news 5", + "newsbox_title": "News 5" + } +}, +{ + "pk": 10, + "model": "myapp_hvad.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-5", + "content_field": "Contenu additionnel de l'actualit\u00e9 5", + "newsbox_slug": "actualite-5", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 5", + "seo_field": "SEO additionnel de l'actualit\u00e9 5", + "master": 5, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 5", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 5", + "newsbox_title": "Actualit\u00e9 5" + } +}, +{ + "pk": 11, + "model": "myapp_hvad.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-6", + "content_field": "Extra content of the news 6", + "newsbox_slug": "news-6", + "newsbox_meta_description": "Meta description of the news 6", + "seo_field": "Extra SEO of the news 6", + "master": 6, + "newsbox_summary": "Summary of the news 6", + "language_code": "en", + "newsbox_body": "Body of the news 6", + "newsbox_title": "News 6" + } +}, +{ + "pk": 12, + "model": "myapp_hvad.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-6", + "content_field": "Contenu additionnel de l'actualit\u00e9 6", + "newsbox_slug": "actualite-6", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 6", + "seo_field": "SEO additionnel de l'actualit\u00e9 6", + "master": 6, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 6", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 6", + "newsbox_title": "Actualit\u00e9 6" + } +}, +{ + "pk": 13, + "model": "myapp_hvad.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "keyword1, keyword2, news-7", + "content_field": "Extra content of the news 7", + "newsbox_slug": "news-7", + "newsbox_meta_description": "Meta description of the news 7", + "seo_field": "Extra SEO of the news 7", + "master": 7, + "newsbox_summary": "Summary of the news 7", + "language_code": "en", + "newsbox_body": "Body of the news 7", + "newsbox_title": "News 7" + } +}, +{ + "pk": 14, + "model": "myapp_hvad.newsextendedtranslation", + "fields": { + "newsbox_meta_keywords": "motclef1, motclef2, actualite-7", + "content_field": "Contenu additionnel de l'actualit\u00e9 7", + "newsbox_slug": "actualite-7", + "newsbox_meta_description": "Meta description de l'actualit\u00e9 7", + "seo_field": "SEO additionnel de l'actualit\u00e9 7", + "master": 7, + "newsbox_summary": "R\u00e9sum\u00e9 de l'actualit\u00e9 7", + "language_code": "fr", + "newsbox_body": "Corps de l'actualit\u00e9 7", + "newsbox_title": "Actualit\u00e9 7" + } +}, +{ + "pk": 1, + "model": "myapp_hvad.newsextended", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-11T13:53:56.517Z", + "newsbox_creation_date": "2014-03-11T13:53:56.124Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": true, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 2, + "model": "myapp_hvad.newsextended", + "fields": { + "newsbox_published": false, + "newsbox_changed_date": "2014-03-11T13:53:57.329Z", + "newsbox_creation_date": "2014-03-11T13:53:56.946Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": true, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 3, + "model": "myapp_hvad.newsextended", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-11T13:53:58.094Z", + "newsbox_creation_date": "2014-03-11T13:53:57.716Z", + "newsbox_publication_start_date": "2020-01-01T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": true, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 4, + "model": "myapp_hvad.newsextended", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-11T13:53:59.046Z", + "newsbox_creation_date": "2014-03-11T13:53:58.487Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": true, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 5, + "model": "myapp_hvad.newsextended", + "fields": { + "newsbox_published": false, + "newsbox_changed_date": "2014-03-11T13:53:59.843Z", + "newsbox_creation_date": "2014-03-11T13:53:59.451Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2014-02-22T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": true, + "newsbox_publication_end_date": "2000-01-01T08:00:00Z" + } +}, +{ + "pk": 6, + "model": "myapp_hvad.newsextended", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-11T13:54:00.657Z", + "newsbox_creation_date": "2014-03-11T13:54:00.246Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2005-07-15T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": false, + "newsbox_publication_end_date": null + } +}, +{ + "pk": 7, + "model": "myapp_hvad.newsextended", + "fields": { + "newsbox_published": true, + "newsbox_changed_date": "2014-03-11T13:54:01.420Z", + "newsbox_creation_date": "2014-03-11T13:54:01.033Z", + "newsbox_publication_start_date": "1985-07-02T08:00:00Z", + "newsbox_date": "2020-01-01T08:00:00Z", + "general_field": "Test", + "newsbox_indexed": true, + "newsbox_publication_end_date": null + } +} +] diff --git a/tests/myapp_hvad/models.py b/tests/myapp_hvad/models.py new file mode 100644 index 0000000..8488585 --- /dev/null +++ b/tests/myapp_hvad/models.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models +from newsbox.models import NewsboxBase, NewsboxSEOBase, NewsboxExpiredBase +from newsbox_hvad.models import NewsboxHVADBase + +class News(NewsboxHVADBase, NewsboxBase): + class Meta: + verbose_name = 'news - HVAD' + verbose_name_plural = 'news - HVAD' + +class NewsComplete(NewsboxHVADBase, NewsboxBase, NewsboxSEOBase, NewsboxExpiredBase): + class Meta: + verbose_name = 'news - CompleteHVAD' + verbose_name_plural = 'news - CompleteHVAD' + +class NewsExtended(NewsboxHVADBase, NewsboxBase, NewsboxSEOBase, NewsboxExpiredBase): + general_field = models.CharField(max_length=50) + content_field = models.CharField(max_length=50) + seo_field = models.CharField(max_length=50) + + class Meta: + verbose_name = 'news - ExtendedHVAD' + verbose_name_plural = 'news - ExtendedHVAD' + newsbox_trans_fieldnames = ['content_field', 'seo_field'] + diff --git a/tests/myapp_hvad/tests.py b/tests/myapp_hvad/tests.py new file mode 100644 index 0000000..60e3504 --- /dev/null +++ b/tests/myapp_hvad/tests.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.test import TestCase, Client +from django.core.paginator import EmptyPage +from django.utils.translation import activate + +from .models import News, NewsComplete, NewsExtended + + + + +class NewsboxAbstractModelsTests(TestCase): + + fixtures = ['tests_data.json',] + + def test_01_manager_published(self): + """ + Test if we only get really published news via the manager + """ + newsClasses = [ + News, NewsComplete, NewsExtended + ] + for cls in newsClasses: + returned_ids = list(cls.objects.published().values_list( + 'id', flat=True).order_by('id')) + self.assertEqual( + (cls.__name__,returned_ids), + (cls.__name__,[1, 4, 6, 7,])) + + def test_02_extra_translated_fields(self): + news = NewsExtended.objects.get(pk=1) + self.assertEqual( + list(news.get_available_languages()), + ['en', 'fr']) + news_fr = NewsExtended.objects.language('fr').get(pk=1) + news_en = NewsExtended.objects.language('en').get(pk=1) + self.assertEqual( + news_fr.content_field, + 'Contenu additionnel de l\'actualité 1') + self.assertEqual( + news_en.content_field, + 'Extra content of the news 1') + self.assertEqual(news_en.general_field, news_fr.general_field) + + def test_03_view_archive_200(self): + """ + Test if generic archive view return right informations. + """ + c = Client() + r = c.get('/en/news/') + + self.assertEqual(r.status_code, 200) + self.assertIn('newsset', r.context) + self.assertEqual(r.context['newsset'][0].pk, 7) + self.assertEqual(r.context['newsset'].number, 1) + self.assertEqual(r.context['newsset'].paginator.num_pages, 4) + self.assertFalse(r.context['newsset'].has_previous()) + self.assertTrue(r.context['newsset'].has_next()) + self.assertRaises(EmptyPage, r.context['newsset'].previous_page_number) + self.assertEqual(r.context['newsset'].next_page_number(), 2) + + + def test_04_view_detail_200(self): + """ + Test if generic day views return right informations. + """ + c = Client() + r = c.get('/en/newsbox/myapp_hvad/news/2005/07/15/news-6/') + self.assertEqual(r.status_code, 200) + self.assertEqual(r.context['news'].pk, 6) + + def test_05_view_detail_404(self): + """ + Test if generic day views return a 404 with an URL with a date without + any news. + """ + c = Client() + r = c.get('/en/newsbox/myapp_hvad/news/1985/07/02/my-birthday/') + self.assertEqual(r.status_code, 404) + + def test_06_view_detail_404_not_published(self): + """ + Test if generic day views return a 404 with an URL with a not published + news + """ + c = Client() + r = c.get('/en/newsbox/myapp_hvad/news/2014/02/22/news-2/') + self.assertEqual(r.status_code, 404) + + def test_07_view_detail_translated(self): + c = Client() + r_en = c.get('/en/newsbox/myapp_hvad/news/2005/07/15/news-6/') + r_fr = c.get('/fr/newsbox/myapp_hvad/news/2005/07/15/actualite-6/') + self.assertEqual(r_fr.context['news'].pk, r_en.context['news'].pk) + self.assertEqual(r_fr.context['news'].newsbox_title, 'Actualité 6') + self.assertEqual(r_en.context['news'].newsbox_title, 'News 6') + + def test_08_get_absolute_url(self): + news6 = News.objects.get(pk=6) + expected_results = { + 'en':'/en/newsbox/myapp_hvad/news/2005/07/15/news-6/', + 'fr':'/fr/newsbox/myapp_hvad/news/2005/07/15/actualite-6/',} + for lang in expected_results: + activate(lang) + self.assertEqual(news6.get_absolute_url(), expected_results[lang]) diff --git a/tests/myapp_hvad/urls.py b/tests/myapp_hvad/urls.py new file mode 100644 index 0000000..04c49fa --- /dev/null +++ b/tests/myapp_hvad/urls.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.conf.urls import url, include +from django.conf.urls.i18n import i18n_patterns +from django.contrib import admin +from django.conf import settings +from newsbox.views import NewsboxYearArchiveView, NewsboxArchiveView + +from .models import News + +admin.autodiscover() + +urlpatterns = i18n_patterns('', + url(r'^admin/', include(admin.site.urls)), + url(r'^', include('newsbox_hvad.urls')), + url(r'^news/$', + NewsboxArchiveView.as_view(model=News, paginate_by=1), + name='news_list',), + url(r'^news/(?P<year>\d{4})/$', + NewsboxYearArchiveView.as_view(model=News, paginate_by=1), + name='news_list_y',), +) diff --git a/tests/runtests.sh b/tests/runtests.sh new file mode 100755 index 0000000..274086a --- /dev/null +++ b/tests/runtests.sh @@ -0,0 +1,26 @@ +#!/bin/sh +export PYTHONPATH="./" + +if [ `which django-admin.py` ] ; then + export DJANGO_ADMIN=django-admin.py +else + export DJANGO_ADMIN=django-admin +fi + +export args="$@" +if [ -z "$args" ] ; then + # avoid running the tests for django.contrib.* (they're in INSTALLED_APPS) + export args=myapp +fi + +if [ "$args" = "myapp_cms" ] ; then + export DJANGO_SETTINGS_MODULE='settings_cms' +elif [ "$args" = "myapp_hvad" ] ; then + export DJANGO_SETTINGS_MODULE='settings_hvad' +elif [ "$args" = "myapp_all" ] ; then + export DJANGO_SETTINGS_MODULE='settings_all' +else + export DJANGO_SETTINGS_MODULE='settings' +fi + +$DJANGO_ADMIN test --traceback --settings=$DJANGO_SETTINGS_MODULE --verbosity 2 --pythonpath="../" "$args" diff --git a/tests/settings.py b/tests/settings.py new file mode 100644 index 0000000..5f1ad52 --- /dev/null +++ b/tests/settings.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +import os + +DIRNAME = os.path.dirname(__file__) +DEBUG = True +TEMPLATE_DEBUG = DEBUG +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': 'mydatabase' + } +} +STATIC_URL = '/static/' +STATICFILES_FINDERS = ( + 'django.contrib.staticfiles.finders.AppDirectoriesFinder', +) +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.staticfiles', + 'django.contrib.admin', + + 'newsbox', + 'myapp', +) +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', +) +# Required for Django 1.4+ +STATIC_URL = '/static/' +# Required for Django 1.5+ +SECRET_KEY = 'abc123' +USE_TZ = True +LANGUAGE_CODE = 'en' +LANGUAGES = [('en', 'English')] +ROOT_URLCONF = 'myapp.urls' diff --git a/tests/settings_all.py b/tests/settings_all.py new file mode 100644 index 0000000..cd68248 --- /dev/null +++ b/tests/settings_all.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +from settings_cms import * + +INSTALLED_APPS = list(INSTALLED_APPS + ('myapp_all',)) +INSTALLED_APPS.remove('myapp_cms') +INSTALLED_APPS = tuple(INSTALLED_APPS) + +LANGUAGES = [('en', 'English',), ('fr', 'French',),] +ROOT_URLCONF = 'myapp_all.urls' +MIDDLEWARE_CLASSES=MIDDLEWARE_CLASSES+( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.locale.LocaleMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', +) +CMS_PLACEHOLDER_CONF = { + 'main': { + 'name': "Main content", + 'plugins': ['NewsPlugin','TextPlugin'], + }, +} diff --git a/tests/settings_cms.py b/tests/settings_cms.py new file mode 100644 index 0000000..aff9a8d --- /dev/null +++ b/tests/settings_cms.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +from settings import * + +SITE_ID = 1 +INSTALLED_APPS = list(INSTALLED_APPS + ( + #cms requirements + 'cms', # django CMS itself + 'mptt', # utilities for implementing a modified pre-order traversal tree + 'menus', # helper for model independent hierarchical website navigation + 'south', # intelligent schema and data migrations + 'sekizai', # for javascript and css management + 'djangocms_admin_style', # for the admin skin. You **must** add 'djangocms_admin_style' in the list before 'django.contrib.admin'. + 'django.contrib.messages', # to enable messages framework (see :ref:`Enable messages <enable-messages>`) + 'djangocms_text_ckeditor', + 'newsbox_cms', + 'myapp_cms', +)) +INSTALLED_APPS.remove('myapp') +INSTALLED_APPS = tuple(INSTALLED_APPS) +MIDDLEWARE_CLASSES = ( + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.locale.LocaleMiddleware', + 'django.middleware.doc.XViewMiddleware', + 'django.middleware.common.CommonMiddleware', + 'cms.middleware.page.CurrentPageMiddleware', + 'cms.middleware.user.CurrentUserMiddleware', + 'cms.middleware.toolbar.ToolbarMiddleware', + 'cms.middleware.language.LanguageCookieMiddleware', +) +TEMPLATE_CONTEXT_PROCESSORS = ( + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + 'django.core.context_processors.i18n', + 'django.core.context_processors.request', + 'django.core.context_processors.media', + 'django.core.context_processors.static', + 'cms.context_processors.cms_settings', + 'sekizai.context_processors.sekizai', +) +CMS_TEMPLATES = ( + ('page.html', 'page'), +) +ROOT_URLCONF = 'myapp_cms.urls' +CMS_PLACEHOLDER_CONF = { + 'main': { + 'name': "Main content", + 'plugins': ['NewsPlugin',], + }, +} diff --git a/tests/settings_hvad.py b/tests/settings_hvad.py new file mode 100644 index 0000000..f549c36 --- /dev/null +++ b/tests/settings_hvad.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +from settings import * + +LANGUAGES = [('en', 'English'),('fr', 'French'),] +ROOT_URLCONF = 'myapp_hvad.urls' +MIDDLEWARE_CLASSES=( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.locale.LocaleMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', +) + +INSTALLED_APPS = list(INSTALLED_APPS + ('hvad', 'myapp_hvad',)) +INSTALLED_APPS.remove('myapp') +INSTALLED_APPS = tuple(INSTALLED_APPS) diff --git a/tests/utils.py b/tests/utils.py new file mode 100644 index 0000000..17a8e09 --- /dev/null +++ b/tests/utils.py @@ -0,0 +1,256 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +from myapp.models import News, NewsExpired, NewsSEO, NewsComplete, NewsExtended +from myapp_cms.models import News as cms_News, \ + NewsComplete as cms_NewsComplete, \ + NewsExtended as cms_NewsExtended +from myapp_hvad.models import News as hvad_News, \ + NewsComplete as hvad_NewsComplete, \ + NewsExtended as hvad_NewsExtended +from myapp_all.models import News as all_News, \ + NewsComplete as all_NewsComplete, \ + NewsExtended as all_NewsExtended +from cms.models.placeholdermodel import Placeholder +from cms.api import add_plugin + +def get_fields_values(newsTypes, newsType, i, inherited): + fields_values={} + if newsType in inherited : + return fields_values + inherited.append(newsType) + + for inheritedType in newsTypes[newsType]['overwrites']['inherit']: + fields_values.update(get_fields_values(newsTypes, inheritedType, i, [])) + if i in newsTypes[newsType]['overwrites']: + fields_values.update(newsTypes[newsType]['overwrites'][i]) + return fields_values + +def create_tests_data(app=None): + + #Translations of translatable fields + translations = { + 'en':{ + #default content is already in english + }, + 'fr':{ + 'newsbox_slug':'actualite-%d', + 'newsbox_title':'Actualité %d', + 'newsbox_summary':'Résumé de l\'actualité %d', + 'newsbox_body':'Corps de l\'actualité %d', + 'newsbox_meta_description':'Meta description de l\'actualité %d', + 'newsbox_meta_keywords':'motclef1, motclef2, actualite-%d', + 'content_field':'Contenu additionnel de l\'actualité %d', + 'seo_field':'SEO additionnel de l\'actualité %d', + }, + } + translatable_fields = translations['fr'].keys() + + #array of available NewsTypes + #for each NewsType, we define a subarray with the model to use and + #default fields values in "overwrites" which is a subarray too : + # - inherit is a list of other NewsTypes to get default fields.from their conf + # - key 0 is the default values for all news + # - keys 1 to N is an array with values to overwrite for news 1 to N. + # Can also contain a "languages" list with language code for translations. + #Only used for HVAD Models. Translations are in "translations" variable. + newsTypes = { + 'News' : { + 'model':News, + 'overwrites':{ + 'inherit':[], + #0 is for base values + 0:{ + 'newsbox_slug':'news-%d', + 'newsbox_title':'News %d', + 'newsbox_date':'2014-02-22T10:00:00+02:00', + 'newsbox_publication_start_date':'1985-07-02T10:00:00+02:00', + 'newsbox_published':True, + 'newsbox_summary':'Summary of the news %d', + 'newsbox_body':'Body of the news %d', + }, + 1:{}, + 2:{'newsbox_published':False}, + 3:{'newsbox_publication_start_date':'2020-01-01T10:00:00+02:00'}, + 4:{'newsbox_body':''}, + 5:{'newsbox_published':False}, + 6:{'newsbox_date':'2005-07-15T10:00:00+02:00'}, + 7:{'newsbox_date':'2020-01-01T10:00:00+02:00'}, + }, + }, + 'NewsExpired' : { + 'model':NewsExpired, + 'overwrites':{ + 'inherit':['News',], + 5:{ + 'newsbox_published':True, + 'newsbox_publication_end_date':'2000-01-01T10:00:00+02:00', + }, + }, + }, + 'NewsSEO' : { + 'model':NewsSEO, + 'overwrites':{ + 'inherit':['News',], + 0:{ + 'newsbox_indexed':True, + 'newsbox_meta_description':'Meta description of the news %d', + 'newsbox_meta_keywords':'keyword1, keyword2, news-%d', + }, + 6:{ + 'newsbox_indexed':False, + }, + }, + }, + 'NewsComplete' : { + 'model':NewsComplete, + 'overwrites':{ + 'inherit':['NewsExpired', 'NewsSEO'], + }, + }, + 'NewsExtended' : { + 'model':NewsExtended, + 'overwrites':{ + 'inherit':['NewsComplete'], + 0:{ + 'general_field':'Test', + 'content_field':'Extra content of the news %d', + 'seo_field':'Extra SEO of the news %d', + }, + } + }, + + #CMS Models + 'cms_News' : { + 'model':cms_News, + 'overwrites':{ + 'inherit':['News',], + 0:{ + 'newsbox_summary':'<p>Summary of the news %d</p>', + 'newsbox_body':'<p>Body of the news %d</p>', + }, + }, + }, + 'cms_NewsComplete' : { + 'model':cms_NewsComplete, + 'overwrites':{ + 'inherit':['NewsComplete', 'cms_News'], + }, + }, + 'cms_NewsExtended' : { + 'model':cms_NewsExtended, + 'overwrites':{ + 'inherit':['cms_NewsComplete'], + }, + }, + + #HVAD Models + 'hvad_News' : { + 'languages':['en', 'fr',], + 'model':hvad_News, + 'overwrites':{ + 'inherit':['News',], + }, + }, + 'hvad_NewsComplete' : { + 'languages':['en', 'fr',], + 'model':hvad_NewsComplete, + 'overwrites':{ + 'inherit':['NewsComplete', 'hvad_News'], + }, + }, + 'hvad_NewsExtended' : { + 'languages':['en', 'fr',], + 'model':hvad_NewsExtended, + 'overwrites':{ + 'inherit':['NewsExtended', 'hvad_NewsComplete'], + }, + }, + + #ALL Models + 'all_News' : { + 'languages':['en', 'fr',], + 'model':all_News, + 'overwrites':{ + 'inherit':['News',], + 0:{ + 'newsbox_summary':'<p>Summary of the news %d</p>', + 'newsbox_body':'<p>Body of the news %d</p>', + }, + }, + }, + 'all_NewsComplete' : { + 'languages':['en', 'fr',], + 'model':all_NewsComplete, + 'overwrites':{ + 'inherit':['NewsComplete', 'all_News'], + }, + }, + 'all_NewsExtended' : { + 'languages':['en', 'fr',], + 'model':all_NewsExtended, + 'overwrites':{ + 'inherit':['NewsExtended', 'all_NewsComplete'], + }, + }, + } + nb_news_a_creer = len(newsTypes['News']['overwrites'])-2 + for newsType, infos in newsTypes.items(): + if app and app +'_' not in newsType: + continue + base_kwargs = get_fields_values(newsTypes, newsType, 0, []) + + + print '\n%s\n' % newsType + '-' * len(newsType) + + for i in range(1, nb_news_a_creer+1): + + if not 'languages' in infos: + infos['languages'] = [None,] + + for lang in infos['languages']: + kwargs = base_kwargs.copy() + kwargs.update(get_fields_values(newsTypes, newsType, i, [])) + #Retrieve translated values if a lang is specified + if lang and lang in translations and translations[lang]: + for k in translations[lang]: + if k in kwargs : + if kwargs[k][0:3] == '<p>': + kwargs[k] = '<p>'+translations[lang][k]+'</p>' + else: + kwargs[k] = translations[lang][k] + + #Add the "nth" informations for fields which need it + for k in kwargs: + if type(kwargs[k]) in (str, unicode) and '%d' in kwargs[k]: + kwargs[k] = kwargs[k] % i + + try: + #Transform field into placeholders if needed + ph_names = getattr(infos['model']._meta, 'placeholder_field_names') + for ph_name in ph_names: + if not ph_name in kwargs: + continue + ph = Placeholder.objects.create(slot=ph_name) + add_plugin(ph, 'TextPlugin', lang if lang != None else 'en', body=kwargs[ph_name]) + kwargs[ph_name] = ph + except AttributeError: + pass + + translatable_values = {k:v + for k, v in kwargs.items() + if k in translatable_fields} + untranslatable_fields = list(set(kwargs) - set(translatable_fields)) + untranslatable_values = {k:v + for k, v in kwargs.items() + if k in untranslatable_fields} + + langstr = ' (%s)' % lang if lang else '' + print ' - %d%s : %s' % (i, langstr, kwargs['newsbox_title']) + if lang == infos['languages'][0]: + news = infos['model'](**untranslatable_values) + + if lang : + news.translate(lang) + for k in translatable_values: + setattr(news, k, translatable_values[k]) + news.save() diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..ba0e97b --- /dev/null +++ b/tox.ini @@ -0,0 +1,77 @@ +[tox] +envlist= + py26-16, + py27-16, + py32-16, + py33-16, + py34-16, + + py26-cms30, + py27-cms30, +; cms seems to be not yet compatible with python 3.0 +; py32-cms30, +; py33-cms30, +; py34-cms30, + +[testenv] +changedir = {toxinidir}/tests + +[testenv:py26-16] +basepython = python2.6 +deps = -r{toxinidir}/test_requirements/django-1.6.txt +commands = ./runtests.sh myapp {posargs} + ./runtests.sh myapp_hvad {posargs} + +[testenv:py27-16] +basepython = python2.7 +deps = -r{toxinidir}/test_requirements/django-1.6.txt +commands = ./runtests.sh myapp {posargs} + ./runtests.sh myapp_hvad {posargs} + +[testenv:py32-16] +basepython = python3.2 +deps = -r{toxinidir}/test_requirements/django-1.6.txt +commands = ./runtests.sh myapp {posargs} +; ./runtests.sh myapp_hvad {posargs} + +[testenv:py33-16] +basepython = python3.3 +deps = -r{toxinidir}/test_requirements/django-1.6.txt +commands = ./runtests.sh myapp {posargs} +; ./runtests.sh myapp_hvad {posargs} + +[testenv:py34-16] +basepython = python3.4 +deps = -r{toxinidir}/test_requirements/django-1.6.txt +commands = ./runtests.sh myapp {posargs} +; ./runtests.sh myapp_hvad {posargs} + +[testenv:py26-cms30] +basepython = python2.6 +deps = -r{toxinidir}/test_requirements/django-1.6_cms-3.0.txt +commands = ./runtests.sh myapp_cms {posargs} + ./runtests.sh myapp_all {posargs} + +[testenv:py27-cms30] +basepython = python2.7 +deps = -r{toxinidir}/test_requirements/django-1.6_cms-3.0.txt +commands = ./runtests.sh myapp_cms {posargs} + ./runtests.sh myapp_all {posargs} + +[testenv:py32-cms30] +basepython = python3.2 +deps = -r{toxinidir}/test_requirements/django-1.6_cms-3.0.txt +commands = ./runtests.sh myapp_cms {posargs} + ./runtests.sh myapp_all {posargs} + +[testenv:py33-cms30] +basepython = python3.3 +deps = -r{toxinidir}/test_requirements/django-1.6_cms-3.0.txt +commands = ./runtests.sh myapp_cms {posargs} + ./runtests.sh myapp_all {posargs} + +[testenv:py34-cms30] +basepython = python3.4 +deps = -r{toxinidir}/test_requirements/django-1.6_cms-3.0.txt +commands = ./runtests.sh myapp_cms {posargs} + ./runtests.sh myapp_all {posargs} -- GitLab