Skip to content

Commit

Permalink
Merge pull request django-cms#4224 from yakky/fix/311-regressions
Browse files Browse the repository at this point in the history
Fix 3.1.1 regressions
  • Loading branch information
yakky committed Jul 1, 2015
2 parents 7faad47 + 11eb1d5 commit 0f820a6
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 85 deletions.
73 changes: 1 addition & 72 deletions cms/cache/choices.py
Original file line number Diff line number Diff line change
@@ -1,78 +1,7 @@
# -*- coding: utf-8 -*-
from collections import defaultdict
from django.conf import settings
from django.utils.datastructures import SortedDict
from django.utils.safestring import mark_safe
from cms.exceptions import LanguageError
from cms.models import Title
from cms.utils import i18n, get_cms_setting


def update_site_and_page_choices(lang=None):
lang = lang or i18n.get_current_language()
SITE_CHOICES_KEY = _site_cache_key(lang)
PAGE_CHOICES_KEY = _page_cache_key(lang)
title_queryset = (Title.objects.drafts()
.select_related('page', 'page__site')
.order_by('page__path'))
pages = defaultdict(SortedDict)
sites = {}
for title in title_queryset:
page = pages[title.page.site.pk].get(title.page.pk, {})
page[title.language] = title
pages[title.page.site.pk][title.page.pk] = page
sites[title.page.site.pk] = title.page.site.name

site_choices = []
page_choices = [('', '----')]

try:
fallbacks = i18n.get_fallback_languages(lang)
except LanguageError:
fallbacks = []
language_order = [lang] + fallbacks

for sitepk, sitename in sites.items():
site_choices.append((sitepk, sitename))

site_page_choices = []
for titles in pages[sitepk].values():
title = None
for language in language_order:
title = titles.get(language)
if title:
break
if not title:
continue

indent = u"  " * (title.page.depth - 1)
page_title = mark_safe(u"%s%s" % (indent, title.title))
site_page_choices.append((title.page.pk, page_title))

page_choices.append((sitename, site_page_choices))
from django.core.cache import cache
# We set it to 1 day here because we actively invalidate this cache.
cache.set(SITE_CHOICES_KEY, site_choices, 86400)
cache.set(PAGE_CHOICES_KEY, page_choices, 86400)
return site_choices, page_choices


def get_site_choices(lang=None):
from django.core.cache import cache
lang = lang or i18n.get_current_language()
site_choices = cache.get(_site_cache_key(lang))
if site_choices is None:
site_choices, page_choices = update_site_and_page_choices(lang)
return site_choices


def get_page_choices(lang=None):
from django.core.cache import cache
lang = lang or i18n.get_current_language()
page_choices = cache.get(_page_cache_key(lang))
if page_choices is None:
site_choices, page_choices = update_site_and_page_choices(lang)
return page_choices
from cms.utils import get_cms_setting


def _site_cache_key(lang):
Expand Down
2 changes: 1 addition & 1 deletion cms/cache/placeholder.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def get_placeholder_cache(placeholder, lang):
def clear_placeholder_cache(placeholder, lang):
from django.core.cache import cache

cache.delete(_placeholder_cache_key(placeholder, lang))
cache.delete(_placeholder_cache_key(placeholder, lang), version=_get_cache_version())


def _placeholder_page_cache_key(page_lookup, lang, site_id, placeholder_name):
Expand Down
6 changes: 3 additions & 3 deletions cms/forms/fields.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# -*- coding: utf-8 -*-
import six

from django.utils.translation import ugettext_lazy as _
from django import forms
from django.contrib.admin.widgets import RelatedFieldWidgetWrapper
from django.forms.fields import EMPTY_VALUES
from django.utils.translation import ugettext_lazy as _

from cms.cache.choices import get_site_choices, get_page_choices
from cms.models.pagemodel import Page
from cms.forms.utils import get_site_choices, get_page_choices
from cms.forms.widgets import PageSelectWidget, PageSmartLinkWidget
from cms.models.pagemodel import Page


class SuperLazyIterator(object):
Expand Down
77 changes: 75 additions & 2 deletions cms/forms/utils.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,84 @@
# -*- coding: utf-8 -*-
from collections import defaultdict

from django.contrib.sites.models import Site
from django.db.models.signals import post_save, post_delete
from django.utils.datastructures import SortedDict
from django.utils.safestring import mark_safe

from cms.cache.choices import clean_site_choices_cache, clean_page_choices_cache
from cms.cache.choices import (clean_site_choices_cache, clean_page_choices_cache,
_site_cache_key, _page_cache_key)
from cms.exceptions import LanguageError
from cms.models import Page, Title
from cms.utils import i18n


def update_site_and_page_choices(lang=None):
lang = lang or i18n.get_current_language()
SITE_CHOICES_KEY = _site_cache_key(lang)
PAGE_CHOICES_KEY = _page_cache_key(lang)
title_queryset = (Title.objects.drafts()
.select_related('page', 'page__site')
.order_by('page__path'))
pages = defaultdict(SortedDict)
sites = {}
for title in title_queryset:
page = pages[title.page.site.pk].get(title.page.pk, {})
page[title.language] = title
pages[title.page.site.pk][title.page.pk] = page
sites[title.page.site.pk] = title.page.site.name

site_choices = []
page_choices = [('', '----')]

try:
fallbacks = i18n.get_fallback_languages(lang)
except LanguageError:
fallbacks = []
language_order = [lang] + fallbacks

for sitepk, sitename in sites.items():
site_choices.append((sitepk, sitename))

site_page_choices = []
for titles in pages[sitepk].values():
title = None
for language in language_order:
title = titles.get(language)
if title:
break
if not title:
continue

indent = u"  " * (title.page.depth - 1)
page_title = mark_safe(u"%s%s" % (indent, title.title))
site_page_choices.append((title.page.pk, page_title))

page_choices.append((sitename, site_page_choices))
from django.core.cache import cache
# We set it to 1 day here because we actively invalidate this cache.
cache.set(SITE_CHOICES_KEY, site_choices, 86400)
cache.set(PAGE_CHOICES_KEY, page_choices, 86400)
return site_choices, page_choices


def get_site_choices(lang=None):
from django.core.cache import cache
lang = lang or i18n.get_current_language()
site_choices = cache.get(_site_cache_key(lang))
if site_choices is None:
site_choices, page_choices = update_site_and_page_choices(lang)
return site_choices


def get_page_choices(lang=None):
from django.core.cache import cache
lang = lang or i18n.get_current_language()
page_choices = cache.get(_page_cache_key(lang))
if page_choices is None:
site_choices, page_choices = update_site_and_page_choices(lang)
return page_choices

from cms.models import Page

post_save.connect(clean_page_choices_cache, sender=Page)
post_save.connect(clean_site_choices_cache, sender=Site)
Expand Down
2 changes: 1 addition & 1 deletion cms/forms/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext as _

from cms.cache.choices import get_site_choices, get_page_choices
from cms.forms.utils import get_site_choices, get_page_choices
from cms.models import Page, PageUser
from cms.templatetags.cms_admin import CMS_ADMIN_ICON_BASE

Expand Down
5 changes: 2 additions & 3 deletions cms/plugin_rendering.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,8 @@ def render_plugins(plugins, context, placeholder, processors=None):
return out


def render_placeholder(placeholder, context_to_copy,
name_fallback="Placeholder", lang=None, default=None, editable=True,
use_cache=True):
def render_placeholder(placeholder, context_to_copy, name_fallback="Placeholder",
lang=None, default=None, editable=True, use_cache=True):
"""
Renders plugins for a placeholder on the given page using shallow copies of the
given context, and returns a string containing the rendered output.
Expand Down
41 changes: 40 additions & 1 deletion cms/tests/cache.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
# -*- coding: utf-8 -*-
from django.template import Template, RequestContext
from django.conf import settings
from sekizai.context import SekizaiContext

from cms.api import add_plugin, create_page
from cms.cache import _get_cache_version
from cms.cache import _get_cache_version, invalidate_cms_page_cache
from cms.models import Page
from cms.plugin_pool import plugin_pool
from cms.plugin_rendering import render_placeholder
from cms.test_utils.project.placeholderapp.models import Example1
from cms.test_utils.project.pluginapp.plugins.caching.cms_plugins import NoCachePlugin, SekizaiPlugin
from cms.test_utils.testcases import CMSTestCase
from cms.test_utils.util.fuzzy_int import FuzzyInt
Expand Down Expand Up @@ -291,3 +294,39 @@ def test_cache_invalidation(self):
page1.publish('en')
response = self.client.get('/en/')
self.assertContains(response, 'Second content')

def test_render_placeholder_cache(self):
"""
Regression test for #4223
Assert that placeholder cache is cleared correctly when a plugin is saved
"""
invalidate_cms_page_cache()
ex = Example1(
char_1='one',
char_2='two',
char_3='tree',
char_4='four'
)
ex.save()
ph1 = ex.placeholder
###
# add the test plugin
##
test_plugin = add_plugin(ph1, u"TextPlugin", u"en", body="Some text")
test_plugin.save()

# asserting initial text
context = SekizaiContext()
context['request'] = self.get_request()
text = render_placeholder(ph1, context)
self.assertEqual(text, "Some text")

# deleting local plugin cache
del ph1._plugins_cache
test_plugin.body = 'Other text'
test_plugin.save()

# plugin text has changed, so the placeholder rendering
text = render_placeholder(ph1, context)
self.assertEqual(text, "Other text")
2 changes: 1 addition & 1 deletion cms/tests/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
ViewRestrictionInlineAdminForm, GlobalPagePermissionAdminForm,
PageUserGroupForm)
from cms.api import create_page, create_page_user, assign_user_to_page
from cms.cache.choices import update_site_and_page_choices, get_site_choices, get_page_choices
from cms.forms.fields import PageSelectFormField, SuperLazyIterator
from cms.forms.utils import update_site_and_page_choices, get_site_choices, get_page_choices
from cms.models import ACCESS_PAGE, ACCESS_PAGE_AND_CHILDREN
from cms.test_utils.testcases import CMSTestCase
from cms.utils.permissions import set_current_user
Expand Down
2 changes: 1 addition & 1 deletion cms/tests/multilingual.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from django.test.utils import override_settings

from cms.api import create_page, create_title, publish_page, add_plugin
from cms.cache.choices import update_site_and_page_choices
from cms.forms.utils import update_site_and_page_choices
from cms.exceptions import LanguageError
from cms.menu import CMSMenu
from cms.models import Title, EmptyTitle
Expand Down

0 comments on commit 0f820a6

Please sign in to comment.