Skip to content

show_placeholder doesn't add CSS #1577

Closed
robertweglarek opened this Issue Jan 8, 2013 · 7 comments

2 participants

@robertweglarek

I use my plugins:

3columns.html:

{% extends 'mainframe.html' %}
{% load cms_tags placeholder_tags %}
{% block content %}
<div class="c3-left clearfix">{% block column-left %}{% placeholder "left_column" or %}{% show_placeholder "left_column" 'homepage' %}{% endplaceholder %}{% endblock %}</div>
<div class="c3-center clearfix">{% block column-center %}{% placeholder "content" %}{% endblock %}</div>
<div class="c3-right clearfix">{% block column-right %}{% placeholder "right_column" or %}{% show_placeholder "right_column" 'homepage' %}{% endplaceholder %}{% endblock %}</div>
{% endblock %}

plugin.html:

{% load i18n sekizai_tags %}
{% addtoblock "css" %}<link rel="stylesheet" href="{{ STATIC_URL }}basic_jobs_trades_countries_listing_plugin/css/style.css" type="text/css" media="screen" />{% endaddtoblock %}
<div class="small-column-closed-wrapper basic-jobs-listing-plugin trades">
    <h2></h2>
    <div class="content">
        <ul class=>
            {% for trade in trades %}
                <li>
                    <a href="#">{{ trade.name }}</a>
                </li>
            {% endfor %}
        </ul>
    </div>
</div>
<div class="small-column-closed-wrapper basic-jobs-listing-plugin countries">
    <h2></h2>
    <div class="content">
        <ul class=>
            {% for country in countries %}
                <li>
                    <a href="#">{{ country.name }}</a>
                </li>
            {% endfor %}
        </ul>
    </div>
</div>

The problem is, after server restart all is ok, but after next page reload (subpage, not index) CSS declared in plugin is not being added. When I change :
html{% show_placeholder "left_column" 'homepage' %} to html{% show_uncached_placeholder "left_column" 'homepage' %} ALL IS OK.

@ojii
ojii commented Jan 8, 2013
@ojii
ojii commented Jan 8, 2013

Okay now I'm at my laptop explain me the situation a little:

show_placeholder by default caches it's result. Therefore, the template is only executed when it hits a cold cache. Since sekizai uses templates, it's blocks are only injected when the template is executed. If show_placeholder hits a warm cache, it just renders the contents from the cache, not executing the templates, thus not triggering sekizai.

The solutions has two steps (the first being optional):

  1. Sekizai implements a way to "watch" for data being added. This will most likely be a context manager.
  2. django CMS caches the sekizai data along the rendered HTML.

Basically in CMS land this would turn _show_placeholder_for_page into something like this:

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)

    content = None

    if cache_result:
        base_key = _get_cache_key('_show_placeholder_for_page', page_lookup, lang, site_id)
        cache_key = _clean_key('%s_placeholder:%s' % (base_key, placeholder_name))
        cached = cache.get(cache_key)
        if cached:
            content = cached['content']
            sekizai.inject_diff(cached['sekizai']) # inject sekizai data into context

    if not content:
        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': ''}
        differ = sekizai.Differ(context) # start watching the context
        content = render_placeholder(placeholder, context, placeholder_name)
        sekizai_diff = differ.get_diff() # get the sekizai changes
    if cache_result:
        cache.set(cache_key, {'content': content, 'sekizai': sekizai_diff}, settings.CMS_CACHE_DURATIONS['content'])

    if content:
        return {'content': mark_safe(content)}
    return {'content': ''}

Which obviously needs sekizai to implement those APIs (I think it's better I do it there rather than the CMS implementing it itself).

If this sounds reasonable I'll starting implementing the required APIs in sekizai.

@ojii ojii was assigned Jan 8, 2013
@robertweglarek

Is it included in 2.4b?

@ojii
ojii commented Jan 17, 2013

no this was not included in 2.4b1

@ojii
ojii commented Jan 17, 2013

@digi604 before the next beta/rc, this really has to be resolved. I'll see how much I can get done tonight to solve this issue.

@ojii
ojii commented Jan 18, 2013

Started work on this and can easily reproduce it in tests. I'm at a hackathon until Sunday so should have plenty of time to resolve this, stay tuned.

@ojii ojii closed this in 513367c Jan 21, 2013
@robertweglarek

Hmm,
i update my libs by:
pip install -U -e git://github.com/divio/django-cms.git@master#egg=django-cm
but I still have to use show_uncached_placeholder.

My plugin contains:

{% addtoblock "css" %}<link rel="stylesheet" href="{{ STATIC_URL }}plugin/css/style.css" type="text/css" media="screen" />{% endaddtoblock %}

My template:

{% block column-right %}
            {% placeholder "right_column" or %}
                {% show_placeholder "right_column" 'homepage' %}
            {% endplaceholder %}
        {% endblock %}

Using show_placeholder still has a bug :/

@yakky yakky added a commit to yakky/django-cms that referenced this issue May 7, 2013
@yakky yakky Backport to 2.3.x fix for #1577 5843e82
@ojii ojii referenced this issue in ojii/django-sekizai May 7, 2013
Closed

addtoblock with template block cache failing #29

@yakky yakky added a commit to yakky/django-cms that referenced this issue May 18, 2013
@yakky yakky Backport to 2.3.x fix for #1577 fe5b8d7
@zoliszeredi zoliszeredi added a commit to pbs/django-cms-smartsnippets that referenced this issue Mar 5, 2014
@zoliszeredi zoliszeredi Fix missing content blocks for cached smartsnippets.
The issue fixed is the restoring in the context object of the Sekizai
content. Normally the content would have been added at the time
the *addtoblock* tag is rendered. Unfortunately this caused missing
css/js content since the addtoblock tag never got rendered. Therefore
the blocks content never got added in the context object.

Sekizai 0.7.0 provides a watch mechanism for the context objects.
This keeps track of what's being added to the context after rendering.
By storing alongside the rendered content, the this context difference
we can restore the missing *addtoblock* contents.

See also: divio/django-cms#1577
586f245
@zoliszeredi zoliszeredi referenced this issue in pbs/django-cms-smartsnippets Mar 5, 2014
Merged

Fix missing content blocks for cached smartsnippets. #42

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.