0

I'm trying to create a portfolio overview page using Django CMS.

I have my detail pages already and they have a placeholder called preview-img. For my portfolio overview page, I need to loop over all detail pages and render that placeholder.

The Django docs tell me that an inclusion tag is the way to go. So I defined my tag (show_portfolio) in the templatetags directory such that it returns the pages:

from django import template
from cms.models.pagemodel import Page
from django.template import RequestContext

register = template.Library()

@register.inclusion_tag('portfolio_item.html', takes_context=True)
def show_portfolio(context, parent_slug):
    cms_pages = Page.objects.public()
    cms_pages = [
        page for page in cms_pages
        if page.parent_page and page.parent_page.get_slug() == parent_slug
    ]
    return {
        'cms_pages': cms_pages,
    }

It simply returns the page objects with a given parent page (via slug).

The template in which I now loop over the cms_pages is this (note the attempt to render each pages' preview show_placeholder):

[portfolio_item.html]

{% load cms_tags %}

<div class="row">
    {% for page in cms_pages %}
        ...
        {% show_placeholder "preview-img" page %}
        ...
    {% endfor %}
</div>

Running this, the server hits an uncaught KeyError (key: request) when trying to evaluate show_placeholder. I do not see the connection to what I'm doing. Where does the request come into play? Is it even possible to use show_placeholder inside the template of an inclusion tag?

Here's the trace for completeness:

Traceback:

File ".../python3.6/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File ".../python3.6/site-packages/django/core/handlers/base.py" in _get_response
  217.                 response = self.process_exception_by_middleware(e, request)

File ".../python3.6/site-packages/django/core/handlers/base.py" in _get_response
  215.                 response = response.render()

File ".../python3.6/site-packages/django/template/response.py" in render
  107.             self.content = self.rendered_content

File ".../python3.6/site-packages/django/template/response.py" in rendered_content
  84.         content = template.render(context, self._request)

File ".../python3.6/site-packages/django/template/backends/django.py" in render
  66.             return self.template.render(context)

File ".../python3.6/site-packages/django/template/base.py" in render
  207.                     return self._render(context)

File ".../python3.6/site-packages/django/template/base.py" in _render
  199.         return self.nodelist.render(context)

File ".../python3.6/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)

File ".../python3.6/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)

File ".../python3.6/site-packages/classytags/core.py" in render
  153.         return self.render_tag(context, **kwargs)

File ".../python3.6/site-packages/sekizai/templatetags/sekizai_tags.py" in render_tag
  93.         rendered_contents = nodelist.render(context)

File ".../python3.6/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)

File ".../python3.6/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)

File ".../python3.6/site-packages/classytags/core.py" in render
  153.         return self.render_tag(context, **kwargs)

File ".../python3.6/site-packages/cms/templatetags/cms_tags.py" in render_tag
  443.             return toolbar.render_with_structure(context, nodelist)

File ".../python3.6/site-packages/cms/toolbar/toolbar.py" in render_with_structure
  498.         rendered_contents = nodelist.render(context)

File ".../python3.6/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)

File ".../python3.6/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)

File ".../python3.6/site-packages/django/template/library.py" in render
  245.         return t.render(new_context)

File ".../python3.6/site-packages/django/template/base.py" in render
  209.                 return self._render(context)

File ".../python3.6/site-packages/django/template/base.py" in _render
  199.         return self.nodelist.render(context)

File ".../python3.6/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)

File ".../python3.6/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)

File ".../python3.6/site-packages/django/template/defaulttags.py" in render
  216.                     nodelist.append(node.render_annotated(context))

File ".../python3.6/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)

File ".../python3.6/site-packages/django/template/library.py" in render
  203.         output = self.func(*resolved_args, **resolved_kwargs)

File ".../python3.6/site-packages/cms/templatetags/cms_tags.py" in _show_placeholder_by_id
  116.     request = context['request']

File ".../python3.6/site-packages/django/template/context.py" in __getitem__
  87.         raise KeyError(key)
Filburt
  • 17,626
  • 12
  • 64
  • 115
random6174
  • 474
  • 4
  • 16
  • Why do you have `takes_context=True` when you don't do anything with the context in `show_portfolio`? Maybe that's what is messing things up... – PoByBolek Nov 16 '18 at 15:51
  • @PoByBolek a leftover from an experiment that I failed to remove before posting. Behavior is unchanged if I remove it, though. Also, cheers 8) – random6174 Nov 16 '18 at 16:25

1 Answers1

1

I got this working in my test setup by explicitly passing the request in the context for the inclusion tag:

from django import template
from cms.models.pagemodel import Page

register = template.Library()

@register.inclusion_tag('portfolio_item.html', takes_context=True)
def show_portfolio(context, parent_slug):
    cms_pages = Page.objects.public()
    cms_pages = [
        page for page in cms_pages
        if page.parent_page and page.parent_page.get_slug() == parent_slug
    ]
    return {
        'request': context.request,
        'cms_pages': cms_pages,
    }
PoByBolek
  • 3,775
  • 3
  • 21
  • 22
  • Will try this out later – random6174 Nov 20 '18 at 11:48
  • If work ever bores you and you feel like spending more time on something other than your private server, feel free to check out my newest question: https://stackoverflow.com/questions/53392124/properly-mount-flask-app-at-location-using-nginx-reverse-proxy /edit: Mentioning ppl seems to be broken – random6174 Nov 20 '18 at 11:50