Пример #1
0
    def test_set_get_placeholder_cache(self):
        # Test with a super-long prefix
        en_context = Context({
            'request':
            self.en_request,
            'cms_content_renderer':
            self.get_content_renderer(self.en_request)
        })
        en_us_context = Context({
            'request':
            self.en_us_request,
            'cms_content_renderer':
            self.get_content_renderer(self.en_us_request)
        })
        en_uk_context = Context({
            'request':
            self.en_uk_request,
            'cms_content_renderer':
            self.get_content_renderer(self.en_uk_request)
        })

        en_content = self.placeholder.render(en_context, 350, lang='en')
        en_us_content = self.placeholder.render(en_us_context, 350, lang='en')
        en_uk_content = self.placeholder.render(en_uk_context, 350, lang='en')

        del self.placeholder._plugins_cache

        de_context = Context({
            'request':
            self.de_request,
            'cms_content_renderer':
            self.get_content_renderer(self.de_request)
        })
        de_content = self.placeholder.render(de_context, 350, lang='de')

        self.assertNotEqual(en_content, de_content)

        set_placeholder_cache(self.placeholder, 'en', 1, en_content,
                              self.en_request)
        cached_en_content = get_placeholder_cache(self.placeholder, 'en', 1,
                                                  self.en_request)
        self.assertEqual(cached_en_content, en_content)

        set_placeholder_cache(self.placeholder, 'de', 1, de_content,
                              self.de_request)
        cached_de_content = get_placeholder_cache(self.placeholder, 'de', 1,
                                                  self.de_request)
        self.assertNotEqual(cached_en_content, cached_de_content)

        set_placeholder_cache(self.placeholder, 'en', 1, en_us_content,
                              self.en_us_request)
        cached_en_us_content = get_placeholder_cache(self.placeholder, 'en', 1,
                                                     self.en_us_request)
        self.assertNotEqual(cached_en_content, cached_en_us_content)

        set_placeholder_cache(self.placeholder, 'en', 1, en_uk_content,
                              self.en_uk_request)
        cached_en_uk_content = get_placeholder_cache(self.placeholder, 'en', 1,
                                                     self.en_uk_request)
        self.assertNotEqual(cached_en_us_content, cached_en_uk_content)
Пример #2
0
    def test_render_placeholder_tag_use_cache(self):
        """
        Tests that {% render_placeholder %} populates cache.
        """
        render_placeholder_body = "I'm the render placeholder body"
        ex1 = Example1(char_1="char_1",
                       char_2="char_2",
                       char_3="char_3",
                       char_4="char_4")
        ex1.save()
        request = self.get_request('/')
        add_plugin(ex1.placeholder,
                   u"TextPlugin",
                   u"en",
                   body=render_placeholder_body)

        template = '{% load cms_tags %}<h1>{% render_placeholder ex1.placeholder %}</h1>'

        cache_value_before = get_placeholder_cache(ex1.placeholder, 'en', 1,
                                                   request)
        self.render(template, self.test_page, {'ex1': ex1})
        cache_value_after = get_placeholder_cache(ex1.placeholder, 'en', 1,
                                                  request)

        self.assertNotEqual(cache_value_before, cache_value_after)
        self.assertIsNone(cache_value_before)
        self.assertIsNotNone(cache_value_after)
Пример #3
0
    def test_set_get_placeholder_cache(self):
        # Test with a super-long prefix
        en_context = Context({'request': self.en_request})
        en_us_context = Context({'request': self.en_us_request})
        en_uk_context = Context({'request': self.en_uk_request})

        en_content = self.placeholder.render(en_context, 350, lang='en')
        en_us_content = self.placeholder.render(en_us_context, 350, lang='en')
        en_uk_content = self.placeholder.render(en_uk_context, 350, lang='en')

        del self.placeholder._plugins_cache

        de_context = Context({'request': self.de_request})
        de_content = self.placeholder.render(de_context, 350, lang='de')

        self.assertNotEqual(en_content, de_content)

        set_placeholder_cache(self.placeholder, 'en', 1, en_content, self.en_request)
        cached_en_content = get_placeholder_cache(self.placeholder, 'en', 1, self.en_request)
        self.assertEqual(cached_en_content, en_content)

        set_placeholder_cache(self.placeholder, 'de', 1, de_content, self.de_request)
        cached_de_content = get_placeholder_cache(self.placeholder, 'de', 1, self.de_request)
        self.assertNotEqual(cached_en_content, cached_de_content)

        set_placeholder_cache(self.placeholder, 'en', 1, en_us_content, self.en_us_request)
        cached_en_us_content = get_placeholder_cache(self.placeholder, 'en', 1, self.en_us_request)
        self.assertNotEqual(cached_en_content, cached_en_us_content)

        set_placeholder_cache(self.placeholder, 'en', 1, en_uk_content, self.en_uk_request)
        cached_en_uk_content = get_placeholder_cache(self.placeholder, 'en', 1, self.en_uk_request)
        self.assertNotEqual(cached_en_us_content, cached_en_uk_content)
Пример #4
0
    def test_show_uncached_placeholder_tag_no_use_cache(self):
        """
        Tests that {% show_uncached_placeholder %} does not populate cache.
        """
        template = '{% load cms_tags %}<h1>{% show_uncached_placeholder "sub" test_page %}</h1>'
        placeholder = self.test_page.placeholders.get(slot='sub')
        request = self.get_request(page=self.test_page)
        cache_value_before = get_placeholder_cache(placeholder, 'en', 1, request)
        output = self.render(template, self.test_page, {'test_page': self.test_page})
        cache_value_after = get_placeholder_cache(placeholder, 'en', 1, request)

        self.assertEqual(output, '<h1>%s</h1>' % self.test_data['text_sub'])
        self.assertEqual(cache_value_before, cache_value_after)
        self.assertIsNone(cache_value_after)
Пример #5
0
    def test_set_get_placeholder_cache_with_long_prefix(self):
        """
        This is for testing that everything continues to work even when the
        cache-keys are hashed.
        """
        # Use an absurdly long cache prefix to get us in the right neighborhood...
        with self.settings(CMS_CACHE_PREFIX="super_lengthy_prefix" *
                           9):  # 180 chars
            en_crazy_request = self.get_request('/en/')
            en_crazy_renderer = self.get_content_renderer(self.de_request)
            # Use a ridiculously long "country code" (80 chars), already we're at 260 chars.
            en_crazy_request.META['HTTP_COUNTRY_CODE'] = 'US' * 40  # 80 chars
            en_crazy_context = Context({'request': en_crazy_request})
            en_crazy_content = en_crazy_renderer.render_placeholder(
                self.placeholder,
                en_crazy_context,
                language='en',
                width=350,
            )
            set_placeholder_cache(self.placeholder, 'en', 1, en_crazy_content,
                                  en_crazy_request)

            # Prove that it is hashed...
            crazy_cache_key = _get_placeholder_cache_key(
                self.placeholder, 'en', 1, en_crazy_request)
            key_length = len(crazy_cache_key)
            # 221 = 180 (prefix length) + 1 (separator) + 40 (sha1 hash)
            self.assertTrue('render_placeholder' not in crazy_cache_key
                            and key_length == 221)

            # Prove it still works as expected
            cached_en_crazy_content = get_placeholder_cache(
                self.placeholder, 'en', 1, en_crazy_request)
            self.assertEqual(en_crazy_content, cached_en_crazy_content)
Пример #6
0
    def _get_cached_placeholder_content(self, placeholder, site_id, language):
        """
        Returns a dictionary mapping placeholder content and sekizai data.
        Returns None if no cache is present.
        """
        # Placeholders can be rendered multiple times under different sites
        # it's important to have a per-site "cache".
        site_cache = self._placeholders_content_cache.setdefault(site_id, {})
        # Placeholders can be rendered multiple times under different languages
        # it's important to have a per-language "cache".
        language_cache = site_cache.setdefault(language, {})

        if placeholder.pk not in language_cache:
            cached_value = get_placeholder_cache(
                placeholder,
                lang=language,
                site_id=site_id,
                request=self.request,
            )

            if cached_value != None:
                # None means nothing in the cache
                # Anything else is a valid value
                language_cache[placeholder.pk] = cached_value
        return language_cache.get(placeholder.pk)
Пример #7
0
    def _get_cached_placeholder_content(self, placeholder, site_id, language):
        """
        Returns a dictionary mapping placeholder content and sekizai data.
        Returns None if no cache is present.
        """
        # Placeholders can be rendered multiple times under different sites
        # it's important to have a per-site "cache".
        site_cache = self._placeholders_content_cache.setdefault(site_id, {})
        # Placeholders can be rendered multiple times under different languages
        # it's important to have a per-language "cache".
        language_cache = site_cache.setdefault(language, {})

        if placeholder.pk not in language_cache:
            cached_value = get_placeholder_cache(
                placeholder,
                lang=language,
                site_id=site_id,
                request=self.request,
            )

            if cached_value != None:
                # None means nothing in the cache
                # Anything else is a valid value
                language_cache[placeholder.pk] = cached_value
        return language_cache.get(placeholder.pk)
Пример #8
0
def get_placeholder_content(context, request, current_page, name, inherit, default):
    edit_mode = getattr(request, 'toolbar', None) and getattr(request.toolbar, 'edit_mode')
    pages = [current_page]
    # don't display inherited plugins in edit mode, so that the user doesn't
    # mistakenly edit/delete them. This is a fix for issue #1303. See the discussion
    # there for possible enhancements
    if inherit and not edit_mode:
        pages = chain([current_page], list(reversed(current_page.get_cached_ancestors())))
    for page in pages:
        placeholder = _get_placeholder(current_page, page, context, name)
        if placeholder is None:
            continue
        if not edit_mode and get_cms_setting('PLACEHOLDER_CACHE'):
            if hasattr(placeholder, 'content_cache'):
                return mark_safe(placeholder.content_cache)
            if not hasattr(placeholder, 'cache_checked'):
                cached_value = get_placeholder_cache(placeholder, get_language())
                if cached_value is not None:
                    restore_sekizai_context(context, cached_value['sekizai'])
                    return mark_safe(cached_value['content'])
        if not get_plugins(request, placeholder, page.get_template()):
            continue
        content = render_placeholder(placeholder, context, name)
        if content:
            return content
            # if we reach this point, we have an empty or non-existant placeholder
            # call _get_placeholder again to get the placeholder properly rendered
            # in frontend editing
    placeholder = _get_placeholder(current_page, current_page, context, name)
    return render_placeholder(placeholder, context, name, default=default)
Пример #9
0
def _get_placeholder(current_page, page, context, name):
    placeholder_cache = getattr(current_page, '_tmp_placeholders_cache', {})
    if page.pk in placeholder_cache:
        placeholder = placeholder_cache[page.pk].get(name, None)
        if placeholder:
            return placeholder
    placeholder_cache[page.pk] = {}
    placeholders = page.rescan_placeholders().values()
    fetch_placeholders = []
    request = context['request']
    if not get_cms_setting('PLACEHOLDER_CACHE') or (hasattr(request, 'toolbar') and request.toolbar.edit_mode):
        fetch_placeholders = placeholders
    else:
        for placeholder in placeholders:
            cached_value = get_placeholder_cache(placeholder, get_language())
            if cached_value is not None:
                restore_sekizai_context(context, cached_value['sekizai'])
                placeholder.content_cache = cached_value['content']
            else:
                fetch_placeholders.append(placeholder)
            placeholder.cache_checked = True
    if fetch_placeholders:
        assign_plugins(context['request'], fetch_placeholders, page.get_template(),  get_language())
    for placeholder in placeholders:
        placeholder_cache[page.pk][placeholder.slot] = placeholder
        placeholder.page = page
    current_page._tmp_placeholders_cache = placeholder_cache
    placeholder = placeholder_cache[page.pk].get(name, None)
    if page.application_urls and not placeholder:
        raise PlaceholderNotFound(
            '"%s" placeholder not found in an apphook application. Please use a static placeholder instead.' % name)
    return placeholder
Пример #10
0
def get_placeholder_content(context, request, current_page, name, inherit, default):
    edit_mode = getattr(request, 'toolbar', None) and getattr(request.toolbar, 'edit_mode')
    pages = [current_page]
    # don't display inherited plugins in edit mode, so that the user doesn't
    # mistakenly edit/delete them. This is a fix for issue #1303. See the discussion
    # there for possible enhancements
    if inherit and not edit_mode:
        pages = chain([current_page], list(reversed(current_page.get_cached_ancestors())))
    for page in pages:
        placeholder = _get_placeholder(current_page, page, context, name)
        if placeholder is None:
            continue
        if not edit_mode and get_cms_setting('PLACEHOLDER_CACHE'):
            if hasattr(placeholder, 'content_cache'):
                return mark_safe(placeholder.content_cache)
            if not hasattr(placeholder, 'cache_checked'):
                site_id = get_site_id(getattr(page, 'site_id', None))
                cached_value = get_placeholder_cache(placeholder, get_language(), site_id, request)
                if cached_value is not None:
                    restore_sekizai_context(context, cached_value['sekizai'])
                    return mark_safe(cached_value['content'])
        if not get_plugins(request, placeholder, page.get_template()):
            continue
        content = render_placeholder(placeholder, context, name)
        if content:
            return content
            # if we reach this point, we have an empty or non-existant placeholder
            # call _get_placeholder again to get the placeholder properly rendered
            # in frontend editing
    placeholder = _get_placeholder(current_page, current_page, context, name)
    return render_placeholder(placeholder, context, name, default=default)
Пример #11
0
def _get_placeholder(current_page, page, context, name):
    placeholder_cache = getattr(current_page, '_tmp_placeholders_cache', {})
    if page.pk in placeholder_cache:
        placeholder = placeholder_cache[page.pk].get(name, None)
        if placeholder:
            return placeholder
    placeholder_cache[page.pk] = {}
    placeholders = page.rescan_placeholders().values()
    fetch_placeholders = []
    request = context['request']
    site_id = page.site_id
    if not get_cms_setting('PLACEHOLDER_CACHE') or (hasattr(request, 'toolbar') and request.toolbar.edit_mode):
        fetch_placeholders = placeholders
    else:
        for placeholder in placeholders:
            cached_value = get_placeholder_cache(placeholder, get_language(), site_id, request)
            if cached_value is not None:
                restore_sekizai_context(context, cached_value['sekizai'])
                placeholder.content_cache = cached_value['content']
            else:
                fetch_placeholders.append(placeholder)
            placeholder.cache_checked = True
    if fetch_placeholders:
        assign_plugins(context['request'], fetch_placeholders, page.get_template(),  get_language())
    for placeholder in placeholders:
        placeholder_cache[page.pk][placeholder.slot] = placeholder
        placeholder.page = page
    current_page._tmp_placeholders_cache = placeholder_cache
    placeholder = placeholder_cache[page.pk].get(name, None)
    if page.application_urls and not placeholder:
        raise PlaceholderNotFound(
            '"%s" placeholder not found in an apphook application. Please use a static placeholder instead.' % name)
    return placeholder
Пример #12
0
    def test_render_uncached_placeholder_tag_no_use_cache(self):
        """
        Tests that {% render_uncached_placeholder %} does not populate cache.
        """
        render_uncached_placeholder_body = "I'm the render uncached placeholder body"
        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3", char_4="char_4")
        ex1.save()

        add_plugin(ex1.placeholder, u"TextPlugin", u"en", body=render_uncached_placeholder_body)

        template = "{% load cms_tags %}<h1>{% render_uncached_placeholder ex1.placeholder %}</h1>"

        cache_value_before = get_placeholder_cache(ex1.placeholder, "en")
        self.render(template, self.test_page, {"ex1": ex1})
        cache_value_after = get_placeholder_cache(ex1.placeholder, "en")

        self.assertEqual(cache_value_before, cache_value_after)
        self.assertIsNone(cache_value_after)
Пример #13
0
    def test_set_get_placeholder_cache(self):
        # Test with a super-long prefix
        en_renderer = self.get_content_renderer(self.en_request)
        en_context = Context({
            'request': self.en_request,
        })
        en_us_renderer = self.get_content_renderer(self.en_us_request)
        en_us_context = Context({
            'request': self.en_us_request,
        })
        en_uk_renderer = self.get_content_renderer(self.en_uk_request)
        en_uk_context = Context({
            'request': self.en_uk_request,
        })

        en_content = en_renderer.render_placeholder(self.placeholder, en_context, 'en', width=350)
        en_us_content = en_us_renderer.render_placeholder(self.placeholder, en_us_context, 'en', width=350)
        en_uk_content = en_uk_renderer.render_placeholder(self.placeholder, en_uk_context, 'en', width=350)

        del self.placeholder._plugins_cache

        de_renderer = self.get_content_renderer(self.de_request)
        de_context = Context({
            'request': self.de_request,
        })
        de_content = de_renderer.render_placeholder(self.placeholder, de_context, 'de', width=350)

        self.assertNotEqual(en_content, de_content)

        set_placeholder_cache(self.placeholder, 'en', 1, en_content, self.en_request)
        cached_en_content = get_placeholder_cache(self.placeholder, 'en', 1, self.en_request)
        self.assertEqual(cached_en_content, en_content)

        set_placeholder_cache(self.placeholder, 'de', 1, de_content, self.de_request)
        cached_de_content = get_placeholder_cache(self.placeholder, 'de', 1, self.de_request)
        self.assertNotEqual(cached_en_content, cached_de_content)

        set_placeholder_cache(self.placeholder, 'en', 1, en_us_content, self.en_us_request)
        cached_en_us_content = get_placeholder_cache(self.placeholder, 'en', 1, self.en_us_request)
        self.assertNotEqual(cached_en_content, cached_en_us_content)

        set_placeholder_cache(self.placeholder, 'en', 1, en_uk_content, self.en_uk_request)
        cached_en_uk_content = get_placeholder_cache(self.placeholder, 'en', 1, self.en_uk_request)
        self.assertNotEqual(cached_en_us_content, cached_en_uk_content)
Пример #14
0
    def test_render_placeholder_tag_use_cache(self):
        """
        Tests that {% render_placeholder %} populates cache.
        """
        render_placeholder_body = "I'm the render placeholder body"
        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
                       char_4="char_4")
        ex1.save()
        request = self.get_request('/')
        add_plugin(ex1.placeholder, u"TextPlugin", u"en", body=render_placeholder_body)

        template = '{% load cms_tags %}<h1>{% render_placeholder ex1.placeholder %}</h1>'

        cache_value_before = get_placeholder_cache(ex1.placeholder, 'en', 1, request)
        self.render(template, self.test_page, {'ex1': ex1})
        cache_value_after = get_placeholder_cache(ex1.placeholder, 'en', 1, request)

        self.assertNotEqual(cache_value_before, cache_value_after)
        self.assertIsNone(cache_value_before)
        self.assertIsNotNone(cache_value_after)
Пример #15
0
def _show_placeholder_for_page(context, placeholder_name, page_lookup, lang=None,
                               site=None, cache_result=True):
    """
    Shows the content of a page with a placeholder name and given lookup
    arguments in the given language.
    This is useful if you want to have some more or less static content that is
    shared among many pages, such as a footer.

    See _get_page_by_untyped_arg() for detailed information on the allowed types
    and their interpretation for the page_lookup argument.
    """
    validate_placeholder_name(placeholder_name)

    request = context.get('request', False)

    site_id = get_site_id(site)

    if not request:
        return {'content': ''}
    if lang is None:
        lang = get_language_from_request(request)

    page = _get_page_by_untyped_arg(page_lookup, request, site_id)
    if not page:
        return {'content': ''}
    try:
        placeholder = page.placeholders.get(slot=placeholder_name)
    except PlaceholderModel.DoesNotExist:
        if settings.DEBUG:
            raise
        return {'content': ''}

    if cache_result:
        cached_value = get_placeholder_cache(placeholder, lang, site_id, request)
        if cached_value:
            restore_sekizai_context(context, cached_value['sekizai'])
            return {'content': mark_safe(cached_value['content'])}
    watcher = Watcher(context)
    content = render_placeholder(placeholder, context, placeholder_name, lang=lang,
                                 use_cache=cache_result)
    changes = watcher.get_changes()

    edit_mode = hasattr(request, 'toolbar') and getattr(request.toolbar, 'edit_mode', False)
    if not edit_mode and placeholder and placeholder.cache_placeholder and get_cms_setting('PLACEHOLDER_CACHE') and cache_result:  # noqa
        set_placeholder_cache(placeholder, lang, site_id, {'content': content, 'sekizai': changes}, request)
    if content:
        return {'content': mark_safe(content)}
    return {'content': ''}
Пример #16
0
def _show_placeholder_for_page(context, placeholder_name, page_lookup, lang=None,
                               site=None, cache_result=True):
    """
    Shows the content of a page with a placeholder name and given lookup
    arguments in the given language.
    This is useful if you want to have some more or less static content that is
    shared among many pages, such as a footer.

    See _get_page_by_untyped_arg() for detailed information on the allowed types
    and their interpretation for the page_lookup argument.
    """
    validate_placeholder_name(placeholder_name)

    request = context.get('request', False)

    site_id = get_site_id(site)

    if not request:
        return {'content': ''}
    if lang is None:
        lang = get_language_from_request(request)

    page = _get_page_by_untyped_arg(page_lookup, request, site_id)
    if not page:
        return {'content': ''}
    try:
        placeholder = page.placeholders.get(slot=placeholder_name)
    except PlaceholderModel.DoesNotExist:
        if settings.DEBUG:
            raise
        return {'content': ''}

    if cache_result:
        cached_value = get_placeholder_cache(placeholder, lang, site_id, request)
        if cached_value:
            restore_sekizai_context(context, cached_value['sekizai'])
            return {'content': mark_safe(cached_value['content'])}
    watcher = Watcher(context)
    content = render_placeholder(placeholder, context, placeholder_name, lang=lang,
                                 use_cache=cache_result)
    changes = watcher.get_changes()

    edit_mode = hasattr(request, 'toolbar') and getattr(request.toolbar, 'edit_mode', False)
    if not edit_mode and placeholder and placeholder.cache_placeholder and get_cms_setting('PLACEHOLDER_CACHE') and cache_result:  # noqa
        set_placeholder_cache(placeholder, lang, site_id, {'content': content, 'sekizai': changes}, request)
    if content:
        return {'content': mark_safe(content)}
    return {'content': ''}
Пример #17
0
    def test_set_get_placeholder_cache_with_long_prefix(self):
        """
        This is for testing that everything continues to work even when the
        cache-keys are hashed.
        """
        # Use an absurdly long cache prefix to get us in the right neighborhood...
        with self.settings(CMS_CACHE_PREFIX="super_lengthy_prefix" * 9):  # 180 chars
            en_crazy_request = self.get_request('/en/')
            # Use a ridiculously long "country code" (80 chars), already we're at 260 chars.
            en_crazy_request.META['HTTP_COUNTRY_CODE'] = 'US' * 40  # 80 chars
            en_crazy_context = Context({'request': en_crazy_request})
            en_crazy_content = self.placeholder.render(en_crazy_context, 350, lang='en')
            set_placeholder_cache(self.placeholder, 'en', 1, en_crazy_content, en_crazy_request)

            # Prove that it is hashed...
            crazy_cache_key = _get_placeholder_cache_key(self.placeholder, 'en', 1, en_crazy_request)
            key_length = len(crazy_cache_key)
            # 213 = 180 (prefix length) + 1 (separator) + 32 (md5 hash)
            self.assertTrue('render_placeholder' not in crazy_cache_key and key_length == 213)

            # Prove it still works as expected
            cached_en_crazy_content = get_placeholder_cache(self.placeholder, 'en', 1, en_crazy_request)
            self.assertEqual(en_crazy_content, cached_en_crazy_content)
Пример #18
0
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.

    Set editable = False to disable front-end editing for this placeholder
    during rendering. This is primarily used for the "as" variant of the
    render_placeholder tag.
    """
    if not placeholder:
        return
    from cms.utils.plugins import get_plugins
    context = context_to_copy.new(context_to_copy)
    context.push()
    request = context['request']
    if not hasattr(request, 'placeholders'):
        request.placeholders = []
    if placeholder.has_change_permission(
            request) or not placeholder.cache_placeholder:
        request.placeholders.append(placeholder)
    if hasattr(placeholder, 'content_cache'):
        return mark_safe(placeholder.content_cache)
    page = placeholder.page if placeholder else None
    # It's kind of duplicate of the similar call in `get_plugins`, but it's required
    # to have a valid language in this function for `get_fallback_languages` to work
    if lang:
        save_language = lang
    else:
        lang = get_language_from_request(request)
        save_language = lang

    # Prepend frontedit toolbar output if applicable
    toolbar = getattr(request, 'toolbar', None)
    if (getattr(toolbar, 'edit_mode', False)
            and getattr(toolbar, "show_toolbar", False)
            and getattr(placeholder, 'is_editable', True) and editable):
        from cms.middleware.toolbar import toolbar_plugin_processor
        processors = (toolbar_plugin_processor, )
        edit = True
    else:
        processors = None
        edit = False
    if get_cms_setting('PLACEHOLDER_CACHE') and use_cache:
        if not edit and placeholder and not hasattr(placeholder,
                                                    'cache_checked'):
            cached_value = get_placeholder_cache(placeholder, lang)
            if not cached_value is None:
                restore_sekizai_context(context, cached_value['sekizai'])
                return mark_safe(cached_value['content'])
    if page:
        template = page.template
    else:
        template = None

    plugins = [
        plugin
        for plugin in get_plugins(request, placeholder, template, lang=lang)
    ]

    # Add extra context as defined in settings, but do not overwrite existing context variables,
    # since settings are general and database/template are specific
    # TODO this should actually happen as a plugin context processor, but these currently overwrite
    # existing context -- maybe change this order?
    slot = getattr(placeholder, 'slot', None)
    if slot:
        for key, value in get_placeholder_conf("extra_context", slot, template,
                                               {}).items():
            if key not in context:
                context[key] = value
    content = []
    watcher = Watcher(context)
    content.extend(render_plugins(plugins, context, placeholder, processors))
    toolbar_content = ''

    if edit and editable:
        # TODO remove ``placeholders`` in 3.3
        if not hasattr(request.toolbar, 'placeholders'):
            request.toolbar.placeholders = {}
        if not hasattr(request.toolbar, 'placeholder_list'):
            request.toolbar.placeholder_list = []
        if placeholder.pk not in request.toolbar.placeholders:
            # TODO remove ``placeholders`` in 3.3
            request.toolbar.placeholders[placeholder.pk] = placeholder
            request.toolbar.placeholder_list.append(placeholder)
        toolbar_content = mark_safe(
            render_placeholder_toolbar(placeholder, context, name_fallback,
                                       save_language))
    if content:
        content = mark_safe("".join(content))
    elif default:
        #should be nodelist from a template
        content = mark_safe(default.render(context_to_copy))
    else:
        content = ''
    context['content'] = content
    context['placeholder'] = toolbar_content
    context['edit'] = edit
    result = render_to_string("cms/toolbar/content.html", context)
    changes = watcher.get_changes()
    if placeholder and not edit and placeholder.cache_placeholder and get_cms_setting(
            'PLACEHOLDER_CACHE') and use_cache:
        set_placeholder_cache(placeholder,
                              lang,
                              content={
                                  'content': result,
                                  'sekizai': changes
                              })
    context.pop()
    return result
Пример #19
0
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.

    Set editable = False to disable front-end editing for this placeholder
    during rendering. This is primarily used for the "as" variant of the
    render_placeholder tag.
    """
    from cms.utils.placeholder import get_placeholder_conf, restore_sekizai_context
    from cms.utils.plugins import get_plugins
    # these are always called before all other plugin context processors
    from sekizai.helpers import Watcher

    if not placeholder:
        return
    context = context_to_copy.new(context_to_copy)
    context.push()
    request = context['request']
    if not hasattr(request, 'placeholders'):
        request.placeholders = []
    if placeholder.has_change_permission(request) or not placeholder.cache_placeholder:
        request.placeholders.append(placeholder)
    if hasattr(placeholder, 'content_cache'):
        return mark_safe(placeholder.content_cache)
    page = placeholder.page if placeholder else None
    # It's kind of duplicate of the similar call in `get_plugins`, but it's required
    # to have a valid language in this function for `get_fallback_languages` to work
    if lang:
        save_language = lang
    else:
        lang = get_language_from_request(request)
        save_language = lang

    # Prepend frontedit toolbar output if applicable
    toolbar = getattr(request, 'toolbar', None)
    if (getattr(toolbar, 'edit_mode', False) and
            getattr(toolbar, "show_toolbar", False) and
            getattr(placeholder, 'is_editable', True) and editable):
        from cms.middleware.toolbar import toolbar_plugin_processor
        processors = (toolbar_plugin_processor, )
        edit = True
    else:
        processors = None
        edit = False
    if get_cms_setting('PLACEHOLDER_CACHE') and use_cache:
        if not edit and placeholder and not hasattr(placeholder, 'cache_checked'):
            cached_value = get_placeholder_cache(placeholder, lang)
            if cached_value is not None:
                restore_sekizai_context(context, cached_value['sekizai'])
                return mark_safe(cached_value['content'])
    if page:
        template = page.template
    else:
        template = None

    plugins = [plugin for plugin in get_plugins(request, placeholder, template, lang=lang)]

    # Add extra context as defined in settings, but do not overwrite existing context variables,
    # since settings are general and database/template are specific
    # TODO this should actually happen as a plugin context processor, but these currently overwrite
    # existing context -- maybe change this order?
    slot = getattr(placeholder, 'slot', None)
    if slot:
        for key, value in get_placeholder_conf("extra_context", slot, template, {}).items():
            if key not in context:
                context[key] = value
    content = []
    watcher = Watcher(context)
    content.extend(render_plugins(plugins, context, placeholder, processors))
    toolbar_content = ''

    if edit and editable:
        # TODO remove ``placeholders`` in 3.3
        if not hasattr(request.toolbar, 'placeholders'):
            request.toolbar.placeholders = {}
        if not hasattr(request.toolbar, 'placeholder_list'):
            request.toolbar.placeholder_list = []
        if placeholder.pk not in request.toolbar.placeholders:
            # TODO remove ``placeholders`` in 3.3
            request.toolbar.placeholders[placeholder.pk] = placeholder
            request.toolbar.placeholder_list.append(placeholder)
        toolbar_content = mark_safe(render_placeholder_toolbar(placeholder, context, name_fallback, save_language))
    if content:
        content = mark_safe("".join(content))
    elif default:
        #should be nodelist from a template
        content = mark_safe(default.render(context_to_copy))
    else:
        content = ''
    context['content'] = content
    context['placeholder'] = toolbar_content
    context['edit'] = edit
    result = render_to_string("cms/toolbar/content.html", context)
    changes = watcher.get_changes()
    if placeholder and not edit and placeholder.cache_placeholder and get_cms_setting('PLACEHOLDER_CACHE') and use_cache:
        set_placeholder_cache(placeholder, lang, content={'content': result, 'sekizai': changes})
    context.pop()
    return result