Search code examples
pythonjinja2pelican

How do I access a specific dictionary element in a Jina2 template?


I have the following dictionary defined in a python config file:

AUTHORS = {
    u'MyName Here': {
        u'blurb': """ blurb about author""",
        u'friendly_name': "Friendly Name",
        u'url': 'http://example.com'
    }
}

I have the following Jinja2 template:

{% macro article_author(article) %}
    {{ article.author }}
    {{ AUTHORS }}
    {% if article.author %}
        <a itemprop="url" href="{{ AUTHORS[article.author]['url'] }}" rel="author"><span itemprop="name">{{ AUTHORS[article.author]['friendly_name'] }}</span></a> -
        {{ AUTHORS[article.author]['blurb'] }}
    {% endif %}
{% endmacro %}

And I call this via:

<div itemprop="author creator" itemscope itemtype="http://schema.org/Person">
    {% from '_includes/article_author.html' import article_author with context %}
    {{ article_author(article) }}
</div>

When I generate my Pelican template I get the following error:

CRITICAL: UndefinedError: dict object has no element <Author u'MyName Here'>

If I remove the {% if article.author %} block from my template, the page generates properly with the {{ AUTHORS }} variable displaying correctly. It clearly has a MyName Here key:

<div itemprop="author creator" itemscope itemtype="http://schema.org/Person">
    MyName Here
    {u'MyName Here': {u'url': u'http://example.com', u'friendly_name': u'Friendly Name', u'blurb': u' blurb about author'}}
</div>

How do I access the MyName Here element correctly in my template?


Solution

  • The article.author isn't just 'Your Name', it's an Author instance with various properties. In your case, you want:

    {% if article.author %}
        <a itemprop="url" href="{{ AUTHORS[article.author.name].url }}" rel="author">
            <span itemprop="name">{{ AUTHORS[article.author.name].friendly_name }}</span>
        </a> -
        {{ AUTHORS[article.author.name].blurb }}
    {% endif %}
    

    or, to reduce some of the boilerplate, you can use:

    {% if article.author %}
        {% with author = AUTHORS[article.author.name] %}
            <a itemprop="url" href="{{ author.url }}" rel="author">
                <span itemprop="name">{{ author.friendly_name }}</span>
            </a> -
            {{ author.blurb }}
        {% endwith %}
    {% endif %}
    

    as long as you have 'jinja2.ext.with_'in your JINJA_ENVIRONMENT's extensions list.

    Note you can use dot.notation rather than index['notation'] in Jinja templates.