Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:divio/django-cms into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
tanderegg committed Feb 27, 2014
2 parents 885ca0c + 3a09d5c commit e66bd00
Show file tree
Hide file tree
Showing 28 changed files with 440 additions and 76 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.txt
Expand Up @@ -188,6 +188,7 @@ Please see Install/2.4 release notes *before* attempting to upgrade to version 2
- moved apphooks from title to page model so we need to add them only once.
- request.current_app has been removed.
- added a namespace field, reverse_id is not used anymore for apphook namespaces.
- PlaceholderAdmin is deprecated and available as mixin class renamed to PlaceholderAdminMixin.
- PlaceholderAdmin does not have LanguageTabs anymore. It only has a PluginAPI now.
- PageAdmin uses the same Plugin API as PlaceholderAdmin
- Toolbar API for your own apps added
Expand Down
6 changes: 5 additions & 1 deletion cms/admin/change_list.py
Expand Up @@ -62,6 +62,10 @@ def __init__(self, request, *args, **kwargs):
def get_query_set(self, request=None):
if COPY_VAR in self.params:
del self.params[COPY_VAR]
if 'language' in self.params:
del self.params['language']
if 'page_id' in self.params:
del self.params['page_id']
if django.VERSION[1] > 3:
qs = super(CMSChangeList, self).get_query_set(request).drafts()
else:
Expand All @@ -82,7 +86,7 @@ def get_query_set(self, request=None):
def is_filtered(self):
from cms.utils.plugins import SITE_VAR
lookup_params = self.params.copy() # a dictionary of the query string
for i in (ALL_VAR, ORDER_VAR, ORDER_TYPE_VAR, SEARCH_VAR, IS_POPUP_VAR, SITE_VAR):
for i in (ALL_VAR, ORDER_VAR, ORDER_TYPE_VAR, SEARCH_VAR, IS_POPUP_VAR, SITE_VAR, 'language', 'page_id'):
if i in lookup_params:
del lookup_params[i]
if not lookup_params.items() and not self.query:
Expand Down
10 changes: 5 additions & 5 deletions cms/admin/pageadmin.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from functools import wraps
import sys
from cms.admin.placeholderadmin import PlaceholderAdmin
from cms.admin.placeholderadmin import PlaceholderAdminMixin
from cms.plugin_pool import plugin_pool
from django.contrib.admin.helpers import AdminForm

Expand All @@ -20,7 +20,7 @@
from django.shortcuts import render_to_response, get_object_or_404
from django.template.context import RequestContext
from django.template.defaultfilters import escape
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext_lazy as _, get_language
from django.utils.decorators import method_decorator
from django.views.decorators.http import require_POST

Expand Down Expand Up @@ -87,7 +87,7 @@ def create_revision():
INITIAL_COMMENT = "Initial version."


class PageAdmin(PlaceholderAdmin, ModelAdmin):
class PageAdmin(PlaceholderAdminMixin, ModelAdmin):
form = PageForm
search_fields = ('title_set__slug', 'title_set__title', 'reverse_id')
revision_form_template = "admin/cms/page/history/revision_header.html"
Expand Down Expand Up @@ -636,6 +636,7 @@ def changelist_view(self, request, extra_context=None):
'has_add_permission': self.has_add_permission(request),
'root_path': reverse('admin:index'),
'app_label': app_label,
'preview_language': request.GET.get('language', get_language()),
'CMS_MEDIA_URL': get_cms_setting('MEDIA_URL'),
'CMS_PERMISSION': get_cms_setting('PERMISSION'),
'DEBUG': settings.DEBUG,
Expand Down Expand Up @@ -1160,8 +1161,7 @@ def change_innavigation(self, request, page_id):
"""
page = get_object_or_404(Page, pk=page_id)
if page.has_change_permission(request):
page.in_navigation = not page.in_navigation
page.save()
page.toggle_in_navigation()
return admin_utils.render_admin_menu_item(request, page)
return HttpResponseForbidden(force_unicode(_("You do not have permission to change this page's in_navigation status")))

Expand Down
15 changes: 11 additions & 4 deletions cms/admin/placeholderadmin.py
Expand Up @@ -35,7 +35,7 @@
from cms.utils.i18n import get_language_list


class FrontendEditableAdmin(object):
class FrontendEditableAdminMixin(object):
frontend_editable_fields = []

def get_urls(self):
Expand All @@ -51,7 +51,7 @@ def get_urls(self):
'',
pat(r'edit-field/([0-9]+)/([a-z\-]+)/$', self.edit_field),
)
return url_patterns + super(FrontendEditableAdmin, self).get_urls()
return url_patterns + super(FrontendEditableAdminMixin, self).get_urls()

def _get_object_for_single_field(self, object_id, language):
# Quick and dirty way to retrieve objects for django-hvad
Expand Down Expand Up @@ -111,7 +111,7 @@ def edit_field(self, request, object_id, language):
return render_to_response('admin/cms/page/plugin/change_form.html', context, RequestContext(request))


class PlaceholderAdmin(ModelAdmin):
class PlaceholderAdminMixin(object):
def get_urls(self):
"""
Register the plugin specific urls (add/edit/copy/remove/move)
Expand All @@ -130,7 +130,7 @@ def get_urls(self):
pat(r'clear-placeholder/([0-9]+)/$', self.clear_placeholder),
pat(r'move-plugin/$', self.move_plugin),
)
return url_patterns + super(PlaceholderAdmin, self).get_urls()
return url_patterns + super(PlaceholderAdminMixin, self).get_urls()

def has_add_plugin_permission(self, request, placeholder, plugin_type):
if not permissions.has_plugin_permission(request.user, plugin_type, "add"):
Expand Down Expand Up @@ -547,3 +547,10 @@ def clear_placeholder(self, request, placeholder_id):
}
return TemplateResponse(request, "admin/cms/page/plugin/delete_confirmation.html", context,
current_app=self.admin_site.name)


class PlaceholderAdmin(PlaceholderAdminMixin, ModelAdmin):
def __init__(self, *args, **kwargs):
warnings.warn("Class PlaceholderAdmin is deprecated and will be removed in 3.1. "
"Instead, combine PlaceholderAdminMixin with admin.ModelAdmin.", DeprecationWarning)
super(PlaceholderAdmin, self).__init__(*args, **kwargs)
4 changes: 2 additions & 2 deletions cms/admin/static_placeholder.py
@@ -1,9 +1,9 @@
from cms.models import StaticPlaceholder
from django.contrib import admin
from cms.admin.placeholderadmin import PlaceholderAdmin
from cms.admin.placeholderadmin import PlaceholderAdminMixin


class StaticPlaceholderAdmin(PlaceholderAdmin):
class StaticPlaceholderAdmin(PlaceholderAdminMixin, admin.ModelAdmin):
list_display = ('name', 'code', 'creation_method')
search_fields = ('name', 'code',)
exclude = ('creation_method',)
Expand Down
19 changes: 15 additions & 4 deletions cms/cms_toolbar.py
Expand Up @@ -2,7 +2,7 @@
import urllib
from cms.compat import user_model_label
from cms.api import get_page_draft
from cms.constants import TEMPLATE_INHERITANCE_MAGIC
from cms.constants import TEMPLATE_INHERITANCE_MAGIC, RIGHT
from cms.exceptions import LanguageError
from cms.models import Title
from cms.toolbar.items import TemplateItem
Expand Down Expand Up @@ -103,7 +103,7 @@ def add_admin_menu(self):
for site in sites_queryset:
sites_menu.add_link_item(site.name, url='http://%s' % site.domain,
active=site.pk == self.current_site.pk)
# admin
# admin
admin_menu.add_sideframe_item(_('Administration'), url=reverse('admin:index'))
admin_menu.add_break(ADMINISTRATION_BREAK)
# cms users
Expand Down Expand Up @@ -142,7 +142,7 @@ def populate(self):
self.change_admin_menu()
if self.page:
self.add_page_menu()
# history menu
# history menu
if self.page and self.toolbar.edit_mode:
self.add_history_menu()
self.change_language_menu()
Expand Down Expand Up @@ -251,7 +251,10 @@ def change_language_menu(self):
def change_admin_menu(self):
admin_menu = self.toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER)
# cms page admin
admin_menu.add_sideframe_item(_('Pages'), url=reverse("admin:cms_page_changelist"), position=0)
url = "%s?language=%s" % (reverse("admin:cms_page_changelist"), self.toolbar.language)
if self.page:
url += "&page_id=%s" % self.page.pk
admin_menu.add_sideframe_item(_('Pages'), url=url, position=0)


def add_page_menu(self):
Expand Down Expand Up @@ -333,6 +336,14 @@ def add_page_menu(self):
current_page_menu.add_modal_item(_('Delete page'), url=delete_url, close_on_url=self.toolbar.URL_CHANGE,
on_close=on_delete_redirect_url, disabled=not_edit_mode)

if not self.title:
self.toolbar.add_button(
_("Page settings"),
"%s?language=%s" % (reverse('admin:cms_page_change', args=[self.page.pk]), self.toolbar.language),
side=self.toolbar.RIGHT,
extra_classes=["cms_btn-action"],
)

def add_history_menu(self):
# history menu
history_menu = self.toolbar.get_or_create_menu('history', _('History'), position=2)
Expand Down
40 changes: 38 additions & 2 deletions cms/models/pagemodel.py
Expand Up @@ -4,7 +4,7 @@
from os.path import join
from cms import constants
from cms.constants import PUBLISHER_STATE_DEFAULT, PUBLISHER_STATE_PENDING, PUBLISHER_STATE_DIRTY, TEMPLATE_INHERITANCE_MAGIC
from cms.exceptions import PublicIsUnmodifiable, LanguageError
from cms.exceptions import PublicIsUnmodifiable, LanguageError, PublicVersionNeeded
from cms.models.managers import PageManager, PagePermissionsPermissionManager
from cms.models.metaclasses import PageMetaClass
from cms.models.placeholdermodel import Placeholder
Expand Down Expand Up @@ -37,6 +37,7 @@ class Page(with_metaclass(PageMetaClass, MPTTModel)):
(1, _('for logged in users only')),
(2, _('for anonymous users only')),
)
TEMPLATE_DEFAULT = TEMPLATE_INHERITANCE_MAGIC if get_cms_setting('TEMPLATE_INHERITANCE') else get_cms_setting('TEMPLATES')[0][0]

X_FRAME_OPTIONS_INHERIT = 0
X_FRAME_OPTIONS_DENY = 1
Expand All @@ -56,6 +57,10 @@ class Page(with_metaclass(PageMetaClass, MPTTModel)):
publication_end_date = models.DateTimeField(_("publication end date"), null=True, blank=True,
help_text=_('When to expire the page. Leave empty to never expire.'),
db_index=True)
#
# Please use toggle_in_navigation() instead of affecting this property
# directly so that the cms page cache can be invalidated as appropriate.
#
in_navigation = models.BooleanField(_("in navigation"), default=True, db_index=True)
soft_root = models.BooleanField(_("soft root"), db_index=True, default=False,
help_text=_("All ancestors will not be displayed in the navigation"))
Expand All @@ -64,7 +69,7 @@ class Page(with_metaclass(PageMetaClass, MPTTModel)):
navigation_extenders = models.CharField(_("attached menu"), max_length=80, db_index=True, blank=True, null=True)
template = models.CharField(_("template"), max_length=100, choices=template_choices,
help_text=_('The template used to render the content.'),
default=TEMPLATE_INHERITANCE_MAGIC)
default=TEMPLATE_DEFAULT)
site = models.ForeignKey(Site, help_text=_('The site the page is accessible at.'), verbose_name=_("site"),
related_name='djangocms_pages')

Expand Down Expand Up @@ -192,6 +197,9 @@ def move_page(self, target, position='first-child'):
public_page.save()
page_utils.check_title_slugs(public_page)

from cms.views import invalidate_cms_page_cache
invalidate_cms_page_cache()

def _copy_titles(self, target, language, published):
"""
Copy all the titles to a new page (which must have a pk).
Expand Down Expand Up @@ -481,6 +489,26 @@ def is_published(self, language, force_reload=False):
except Title.DoesNotExist:
return False

def toggle_in_navigation(self, set_to=None):
'''
Toggles (or sets) in_navigation and invalidates the cms page cache
'''
old = self.in_navigation
if set_to in [True, False]:
self.in_navigation = set_to
else:
self.in_navigation = not self.in_navigation
self.save()

#
# If there was a change, invalidate the cms page cache
#
if self.in_navigation != old:
from cms.views import invalidate_cms_page_cache
invalidate_cms_page_cache()

return self.in_navigation

def get_publisher_state(self, language, force_reload=False):
from cms.models import Title

Expand Down Expand Up @@ -604,6 +632,9 @@ def publish(self, language):

cms_signals.post_publish.send(sender=Page, instance=self, language=language)

from cms.views import invalidate_cms_page_cache
invalidate_cms_page_cache()

return published

def unpublish(self, language):
Expand Down Expand Up @@ -634,8 +665,13 @@ def unpublish(self, language):
# trigger update home
self.save()
self.mark_descendants_pending(language)

from cms.views import invalidate_cms_page_cache
invalidate_cms_page_cache()

from cms.signals import post_unpublish
post_unpublish.send(sender=Page, instance=self, language=language)

return True

def mark_descendants_pending(self, language):
Expand Down
8 changes: 4 additions & 4 deletions cms/models/placeholdermodel.py
Expand Up @@ -130,8 +130,8 @@ def _get_attached_fields(self):
for rel in self._meta.get_all_related_objects():
if issubclass(rel.model, CMSPlugin):
continue
from cms.admin.placeholderadmin import PlaceholderAdmin
if rel.model in admin.site._registry and isinstance(admin.site._registry[rel.model], PlaceholderAdmin):
from cms.admin.placeholderadmin import PlaceholderAdminMixin
if rel.model in admin.site._registry and isinstance(admin.site._registry[rel.model], PlaceholderAdminMixin):
field = getattr(self, rel.get_accessor_name())
if field.count():
self._attached_fields_cache.append(rel.field)
Expand All @@ -149,8 +149,8 @@ def _get_attached_field(self):
for rel in relations:
if issubclass(rel.model, CMSPlugin):
continue
from cms.admin.placeholderadmin import PlaceholderAdmin
if rel.model in admin.site._registry and isinstance(admin.site._registry[rel.model], PlaceholderAdmin):
from cms.admin.placeholderadmin import PlaceholderAdminMixin
if rel.model in admin.site._registry and isinstance(admin.site._registry[rel.model], PlaceholderAdminMixin):
field = getattr(self, rel.get_accessor_name())
if field.count():
self._attached_field_cache = rel.field
Expand Down
7 changes: 7 additions & 0 deletions cms/signals/apphook.py
Expand Up @@ -26,6 +26,9 @@ def apphook_post_page_checker(page):
if (old_page and (
old_page.application_urls != page.application_urls or old_page.application_namespace != page.application_namespace)) or (
not old_page and page.application_urls):

from cms.views import invalidate_cms_page_cache
invalidate_cms_page_cache()
request_finished.connect(trigger_restart, dispatch_uid=DISPATCH_UID)


Expand Down Expand Up @@ -53,6 +56,8 @@ def apphook_post_delete_title_checker(instance, **kwargs):
Check if this was an apphook
"""
if instance.page.application_urls:
from cms.views import invalidate_cms_page_cache
invalidate_cms_page_cache()
request_finished.connect(trigger_restart, dispatch_uid=DISPATCH_UID)


Expand All @@ -61,6 +66,8 @@ def apphook_post_delete_page_checker(instance, **kwargs):
Check if this was an apphook
"""
if instance.application_urls:
from cms.views import invalidate_cms_page_cache
invalidate_cms_page_cache()
request_finished.connect(trigger_restart, dispatch_uid=DISPATCH_UID)

# import the logging library
Expand Down

0 comments on commit e66bd00

Please sign in to comment.