Django==1.5.1
django-cms==2.4.1
I'd like to make something like a summary view from all the child pages of a selected page in django-cms, pulling out title, truncated content etc with a more... link for each listed child. I've managed to get titles and paths just fine, but im struggling to get content from the placeholders.
I have a templatetag like this:
from cms.models import Page
from cms.utils.page_resolver import get_page_from_path
from django import template
register = template.Library()
#register.inclusion_tag('news_summary_item.html')
def get_news_items():
news_root = get_page_from_path('news')
newsitems = news_root.children.filter(published=True)
return {'newsitems':newsitems}
and here is the template its using:
{% load cms_tags menu_tags %}
<ul>
{% for item in newsitems %}
<li>{{ item.get_title }}
{% for placeholder in item.placeholders.all %}
# {% show_placeholder placeholder.slot item current_language %} #
{% endfor %}
</li>
{% endfor %}
</ul>
Can anyone help with getting the placeholder content here? Ideally, id like to be able to pass it through truncatewords_html to just get a summary, but open to other ways to get the same effect.
Thanks for any tips/pointers!
I had to index CMS content in one project and I get the content of each placeholder, and the content of a placeholder is stored in the plugins attached to it
How te get the content of a CMSPlugin in a view?
from cms.models import CMSPlugin
plugin = CMSPlugin.objects.filter(plugin_type='TextPlugin')[0] # Get first text plugin
# This return the body/content of the plugin:
plugin_content = plugin.get_plugin_instance()[0].body
If you would like to manage other plugins like PicturePlugin you could get the "alt" text like:
plugin_picture_content = plugin.get_plugin_instance()[0].alt
How to get the content of CMSPlugin in a template?
# plugin_object containing a CMSPlugin
{{plugin_object.get_plugin_instance.0.body}}
I supose when you want to get the content, we are talking about TextPlugin, you have to be carefull here because only the plugin type TextPlugin has the attribute body, the PicturePlugin has the attribute alt and the LinkPlugin has the attribute href etc...
Solution adapted for your problem
You are doing a loop over placeholders, so you need to get all the plugins for each placeholder and get the content of each plugin, because the content of the placeholders as I mentioned before are stored in the plugins attached to it (TextPlugin, PicturePlugin, LinkPlugin...).
... ... ...
{% for placeholder in item.placeholders.all %} # Loop over placeholders
{% for plugin in placeholder.get_plugin_list %} # Get plugins for each placeholder
{{plugin.get_plugin_instance.0.body|striptags}}
{% endfor %}
{% endfor %}
... ... ...
And to ensure that you only show the content of TextPlugin and not from other plugins you could do:
... ... ...
{% for placeholder in item.placeholders.all %} # Loop over placeholders
{% for plugin in placeholder.get_plugin_list %} # Get plugins for each placeholder
{% if 'TextPlugin' in plugin.plugin_type %}
{{plugin.get_plugin_instance.0.body|striptags}}
{% endif %}
{% endfor %}
{% endfor %}
... ... ...
Related
i have many html files (all of them are same) i useing base.html , but i want to define which html show, for examole when something.com/love loaded show love content, if something.com/game loaded show game content. how define this? and where define? in views.py or in html?
{% for lov in lovess %}
{% if forloop.last %}
love Content text{{lov.body_text}}
{% endif %}
{% endfor %}
if game urls loaded shows game body text.
i do not want to copy paste and create many html files (DRY) , i want to used one basic which are extends in html files.
views.py
Code with your style:
if request.path == "/love/":
temolate = "love.html"
if request.path == "/game/":
temolate = "game.html"
return render(request, temolate)
base.html:
......
{%block content%}
{%endblock%
......
love.html:
{%extends base.html%}
...
{%block content%}
contents of love.
{%endblock%}
...
How do I create a template filter that only shows a section of code on a specified page? For example, my homepage which is my base_generic has code that is specific to that page. Whenever another page is loaded that code should not be displayed.
I know I can use the block system but was wondering if I could also accomplish the task with a combination of the URL and If filter. See code below:
# Code for base_generic template
{% url 'organizer-homepage' as home_page %}
{% if home_page %}
Shows Content Only on Specified Page
{% else %} Show Alternate on All Other Pages
{% endif %}
You can do something like:
{% url 'organizer-homepage' as home_page %}
{% if request.path == home_page %}
Shows Content Only on Specified Page
{% else %} Show Alternate on All Other Pages
{% endif %}
Also make sure you have django.core.context_processors.request in your template context processors, which is there by default.
I use Python 3.4 + Django 1.7.1 with Eclipse - PyDev and I use AcroEdit to edit HTML.
I think AcroEdit uses two soft spaces for indent.
I made a custom template tag named custom_tag in custom_tag_library.py like:
# -*- coding: utf-8 -*-
from django import template
from _ast import Num
register = template.Library()
#register.inclusion_tag('custom_tag.html')
def custom_tag(content):
return {'content': content, 'children': content.children.all()}
and for custom_tag.html:
{% load custom_tag_library %}
<div class = 'a'>
{{ content.name }}
{% if children %}
<div class = 'b'>
{% for child in children %}
{% custom_tag child %}
{% endfor %}
</div>
{% endif %}
</div>
(As you can see, content object has name and children)
So, custom_tag is a recursive tag gives a tree structure represented in <div> hierarchy.
But when I use this, the output HTML has many spaces and empty lines like this:
I tried {% spaceless %} {% endspaceless %}, but it doesn't work.
I think this appears because I use indents to increase readability for my codes. But I want to maintain my coding style about the indentation.
How can I fix this?
I've got exactly the same problem. You want to have clean template html files, that you can easily read (what you got), and you want at the same time to have human readable html when you render it.
So you won't be happy with the solution of changing your templatetag.html file to something like this, which looks like old php spaghetti :
{% load custom_tag_library %}
<div class = 'a'>{{ content.name }}
{% if children %}<div class = 'b'>
{% for child in children %}{% custom_tag child %}{% if not forloop.last %}
{% endif %}{% endfor %}
</div>{% endif %}
</div>
The second solution (and also the best one) is to have a middleware to read and rewrite every HttpResponse to something more tidy.
You can find exactly what you want on the PyEvolve website. What it does is basically :
Parse your HttpResponse html with BeautifulSoup
Prettify it (with cool indent)
Return it as the new HttpResponse
But with this solution, you might have performence issue.
I'm building a website using django with a header on top of every page, which basically is a menu with a few links, constant throughout the pages.
However, depending on the page you're on I'd like to highlight the corresponding link on the menu by adding the class "active". To do so, I am currently doing as follow: each page has a full menu block that integrates within a general layout, which does NOT contain the menu. For exemple, page2 would look like this:
{% extends "layout.html" %}
{% block menu %}
<li>Home</li>
<li>page1</li>
<li class="active">page2</li>
<li>page3</li>
{% endblock %}
The problem is that, beside from that solution being not so pretty, every time I want to add a link to the header menu I have to modify each and every page I have. Since this is far from optimal, I was wondering if any of you would know about a better way of doing so.
Thanks in advance!
You can create a custom templatetag:
from django import template
from django.core.urlresolvers import reverse, NoReverseMatch, resolve
register = template.Library()
#register.simple_tag
def active(request, view_name):
url = resolve(request.path)
if url.view_name == view_name:
return 'active'
try:
uri = reverse(view_name)
except NoReverseMatch:
uri = view_name
if request.path.startswith(uri):
return 'active'
return ''
And use it in the template to recognize which page is loaded by URL
<li class="{% active request 'car_edit' %}">Edit</li>
If you have a "page" object at every view, you could compare a navigation item's slug to the object's slug
navigation.html
<ul>
{% for page in navigation %}
<li{% ifequal object.slug page.slug %} class="active"{% endifequal %}>
{{ page.title }}
</li>
{% endfor %}
</ul>
base.html
<html>
<head />
<body>
{% include "navigation.html" %}
{% block content %}
Welcome Earthling.
{% endblock %}
</body>
</html>
page.html
{% extends "base.html" %}
{% block content %}
{{ object }}
{% endblock %}
Where navigation is perhaps a context_processor variable holding all the pages, and object is the current PageDetailView object variable
Disclaimer
There are many solutions for your problem as noted by Paulo. Of course this solution assumes that every view holds a page object, a concept usually implemented by a CMS. If you have views that do not derive from the Page app you would have to inject page pretenders within the navigation (atleast holding a get_absolute_url and title attribute).
This might be a very nice learning experience, but you'll probably save loads time installing feinCMS or django-cms which both define an ApplicationContent principle also.
You may use the include tag and pass it a value which is the current page.
For example, this may be a separate file for declaring the menu template only:
menu.html
{% if active = "a" %}
<li>Home</li>
{% if active = "b" %}
<li>page1</li>
{% if active = "c" %}
<li class="active">page2</li>
{% if active = "d" %}
<li>page3</li>
And call this from within your template like this:
{% include 'path/to/menu.html' with active="b"%} # or a or c or d.
Hope it helps!
I have a template tag located in catalog/templatetags/catalog_tags.py, which looks like this:
register = template.Library()
#register.inclusion_tag("tags/navigation.html")
def nav_links():
flatpage_list = FlatPage.objects.all()
return {'flatpage_list': flatpage_list }
I have a catalog.html which has {% load catalog_tags %}, to load that tag, and is followed by an inclusion tag for my navigation, {% include "tags/navigation.html" %}.
navigation.html contains the following:
{% with flatpage_list as pages %}
{% for page in pages %}
{{ page.title }}
{% endfor %}
{% endwith %}
But the list of flat_pages is not appearing in my navigation section. Why is that?
If I understand right, with your current state you have something liek this in catalog.html template:
{% load catalog_tags %}
.....
{% include "tags/navigation.html" %}
What this code does, is just renders the "tags/navigation.html" template, nothing more. So your custom template tag is not hit at all. To fix it, you should replace include with nav_links:
{% load catalog_tags %}
.....
{% nav_links %}
See Django docs for reference.
Not sure if it's just a copy paste error or not but return {'flatpage_list': flatpage_list isn't closed properly return {'flatpage_list': flatpage_list}
Also could this be something more suited for a context processor?
EDIT: After reading the other answer, I realized what you are trying to do, when you were using the {% include ... %} tag it seemed like you just wanted to populate the flatpage_list