What would cause the same Django template include block to behave differently twice on the same page? - python-3.x

I'm trying to include a simple pagination template into a template that lists blog posts, but it gets output without getting interpreted, as in, I see the double curly brace enclosed tag as text in the resultant webpage (see image below).
Strangely, when I also paste same block higher in the page, and it gets interpreted fine. The same include, twice on the same page, different behavior!
Between the two, I iterate over the same object that gets passed to the pagination template, so this is probably something that I don't understand about the state of that object? Or Django's rendering process.
{% extends "blog/base.html" %}
{% block title %}My blog site thing{% endblock %}
{% block content %}
<h1>Blog site</h1>
{% include 'pagination.html' with page_object=posts %}
{% for post in posts %}
<h2>{{ post.title }}</h2>
<p class="date">Published {{post.publish}} by {{post.author}}</p>
{{post.body|truncatewords:5|linebreaks}}
{% endfor %}
{% include 'pagination.html' with page_object=posts %}
{% endblock %}
Pagination.html
<div class="pagination">
<span class="step-links">
{% if page_object.has_previous %}
Previous
{% endif %}
<span class="current">
Page {{ page_object.number }} of {{ page_object.paginator.num_pages }}.
</span>
{% if page_object.has_next %}
Next
{% endif %}
</span>
</div>
views.py for this app
from django.shortcuts import render, get_object_or_404
from .models import Post
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
def post_list(request):
object_list = Post.published.all()
paginator = Paginator(object_list, 3)
page = request.GET.get('page')
try:
posts = paginator.page(page)
except PageNotAnInteger:
posts = paginator.page(1)
except EmptyPage:
posts = paginator.page(paginator.num_pages)
return render(request, 'blog/post/list.html', {'posts':posts})
def post_detail(request, year, month, day, post):
post = get_object_or_404(Post, slug=post, status='published',publish__year=year,publish__month=month, publish__day=day)
return render(request, 'blog/post/detail.html', {'post':post})
Here's what the resultant page looks like:
Here's the resultant html (I've added an extra line around the offending output to call it out)
<!DOCTYPE html>
<html>
<head>
<title>My blog site thing</title>
<link href="/static/css/blog.css" rel="stylesheet">
</head>
</html>
<body>
<div id="content">
<h1>Blog site</h1>
<div class="pagination">
<span class="step-links">
<span class="current">
Page 1 of 2.
</span>
Next
</span>
</div>
<h2>Another glorious post</h2>
<p class="date">Published March 2, 2022, 9:26 p.m. by admin</p>
<p>Lorem ipsum text Lorem ipsum …</p>
<h2>Classy post</h2>
<p class="date">Published March 2, 2022, 9:25 p.m. by admin</p>
<p>This is the way</p>
<h2>Another post</h2>
<p class="date">Published March 1, 2022, 7:26 a.m. by admin</p>
<p>Xyz</p>
{% include 'pagination.html' with page_object=posts %}
</div>
<div id="sidebar">
<h2>My blog</h2>
<p>This is my blog.</p>
</div>
</body>
I've even gone back and copy-pasted the actual code from the book I'm following (Django 3 by example, by Antonio Mele) and it's identical!
To any kind soul who has read this far, what am I missing?

Ok, so I just understood what was going on, and sharing in case it's useful to anyone else.
My IDE was mangling the formatting of the template file on save.
So the first include was a perfect little
{% include 'pagination.html' with page=posts %}
The second one ended up looking like
{% include
'pagination.html' with page=posts %}
When I turned off the auto-formatting and fixed the whitespace, it rendered fine.
So my big learning – probably obvious to many – is that whitespace matters in django template tags!.

Related

Flask: How to output string from Python but displayed as hyperlinks in HTML

So, I'm getting the user input from a HTML textbox, and then returning some urls. But currently, when I directly return the URLS (in string), the HTML urls output aren't clickable; they're in just plaintext. Is there a way to convert the returned python strings to HTML urls?
I can change the format of the returned urls on the python side to anything that can be converted to HTML urls that's clickable.
Python code:
#this gets the query and then returns urls
#app.route('/output', methods=['POST'])
def output():
query_list = request.form['query']
outputResults = someFunction(query_list)
return render_template("output.html", output=outputResults)
HTML code:
{% extends 'layout.html' %}
{% block body %}
<div class="jumbotron text-left">
<body>
<style> p {white-space: pre-wrap; }</style>
<h1>Output</h1>
<p> {{output}}
</p>
</body>
</div>
{% endblock %}
Thanks
if you have multiple links in your query use for loop in your template like this:
{% extends 'layout.html' %}
{% block body %}
<div class="jumbotron text-left">
<body>
<style> p {white-space: pre-wrap; }</style>
<h1>Output</h1>
{% for link in output %}
title_your_link
{% endfor %}
</body>
</div>
{% endblock %}

Django cms Template for loop breaks itself during rendering

ive written an simple plugin but it changes the tree, so that the .container moves after the .head, if it trys to render this part:
<a class="head" href="#">
<div class="container">
{% for subchild in child.children %}
<a>{{ subchild }}</a>
{% empty %}
notext
{% endfor %}
</div>
</a>
but if i change the outter a tag to anything else it works

Grav CMS Custom Page Template in Bootstrap: putting different content into rows and columns

I have been following the Grav documentation (https://learn.getgrav.org/cookbook/general-recipes#render-content-in-columns) to figure out how to do this, but haven't had much luck. The content for my page is in default.md, but I can't figure out to how place images and content into separate columns and rows.
I've included a screenshot of what I've created in HTML and CSS. Basically I want to put an image into the left column of a row, and details into the right column. See here: http://imgur.com/HuTSGw5
When I am editing the page template however, I only seem to have one "variable" (if that's the right word) controlling all the content. See my code for base.html.twig:
<div class="container">
<div class="row">
<div class="col-md-4">
{% block content %} {# thumbnail image goes here #}
{% endblock %}
</div> <!-- COLUMN END -->
<div class="col-md-8">
{% block content %} {# album details go here #}
{% endblock %}
</div> <!-- COLUMN END -->
</div> <!-- ROW END -->
How do I specify that a content block is specific for an image, and that another is specific for album details?
{% block content %} is the only block available when showing data from the .md file.
To render the data (text or images) in two or more columns as shown in the documentation, you have to split them in the .md file (with ---) and then use the twig function {% for %} in your .html.twig template to show them.
user/pages/my-2-column-page.md
(note the extra line before the ---)
---
title: ' 2 Columns Page'
---
Column one is for the image thumb
![the thumbnail](../my-2-column-page/thumbnail.jpg)
---
Here goes all the album details content.
Phasellus id eleifend risus. In dui tellus, dignissim id
viverra non, convallis sed ante. Suspendisse
---
user/themes/mytheme/templates/my-2-column-page.html.twig
(note the twig function {% for %} )
{% extends 'partials/base.html.twig' %}
{% block content %}
{% set colsize = [4, 8] %}
<div class="container">
<div class="row">
{% for key, column in page.content|split('<hr />') %}
<div class="col-md-{{ colsize[key] }}">
{{ column }}
</div>
{% endfor %}
</div>
</div>
{% endblock %}
OR ...
Other way to do it (more simple) is to define your .html.twig template as normal (with no "for" iteration) and call the image directly:
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-4">
<img src="{{ page.media['thumbnail.jpg'].url }}" />
</div>
<div class="col-md-8">
{{ page.content }}
</div>
</div>
</div>
{% endblock %}
The image filename must match the file copied in the page folder (user/pages/my-2-column-page/thumbnail.jpg) and just type the album detail in the .md file.

Unique page identifiers in Grav CMS

I'm using the Grav CMS to create a modular web page; however, I'm having difficulty customizing the layout based on how the content is generated.
I've followed the documentation found Grav main site from which I've model my site after.
My folder structure is essentially:
pages
01.home
_section1
_section2
In each section folder I have my .md file. And each section is considered a sub-page of 'home'.
I've created the template file, modular.html.twig, in which I have the following code:
{% extends 'partials/base.html.twig' %}
{% block content %}
{% for child in page.children() %}
{{ child.content() }}
{% endfor %}
{% endblock %}
This code iterates through sub-pages to load the content onto the home page. In my template I'm simply printing the result of the content using {{ content }}
What I end up with is a page with vertically stacked content and repeating html,
as such.
What I want to do is uniquely define each sub-page (section) so that I can manipulate the content differently in my html, as such.
I've thought about creating separate template files for each section, but much of my content is nested.
For instance I have something akin to:
<div class="row">
<div class="section-1">
<h1>{{ content }}</h1> <!--Needs to be unique-->
</div>
<div class="section-2">
<h1>{{ content }}</h1> <!--Needs to be unique-->
</div>
</div>
Is it possible to accomplish what I'm trying to do with this framework? If so, how might I go about it?
Thank you
I think there are many ways to do this. For me, I use page's header to set CSS class of each section.
My section's md files could look like this (for example mysection.md)
---
title: Section 1
section_class: section-1
---
This is the content of section 1.
Here is my modular.html.twig:
{% extends 'partials/base.html.twig' %}
{% block content %}
<div class="row">
{% for child in page.children() %}
<div class="{{ child.header.section_class }}">
{{ child.content() }}
</div>
{% endfor %}
</div>
{% endblock %}
In my mysection.html.twig I print the section's content
<h1>{{ page.content }}</h1>
I hope this helps.

Jekyll paginate blog as subdirectory

I'm using Jekyll for a static site and I'm trying to generate the blog as a subdirectory/subfolder:
http://example.com/blog
In the directory structure before running jekyll, this is blog/index.html.
I tried adding pagination by adding "paginate: 5" to _config.yml, but the generated url's were of the form:
http://example.com/page2/
i.e. no "/blog". This is fixed by:
paginate_path: /blog/page/:num
in _config.yml.
But the resulting generated pages at:
http://example.com/blog/page/2/
don't use blog/index.html as their layout. They use the root index.html. What's the point in even having the paginate_path option, then?
How do I get my blog at example.com/blog, with pagination, using Jekyll?
Use the destination key in your _config.yml file to set the base path where you want the output to be published to. For example,
paginate: 5
destination: _site/blog
Note that assuming your site is setup to server its root (e.g. "http://example.com/") from "_site" jekyll won't produce and "index.html" page at that location. Everything that jekyll builds will be under the "blog" directory, but that sounds like what you are after.
I found a fix via this page Basically it involves a bit of a hack to figure out if you are on the nth page of the blog and then includes a file that pulls in you blog section.
Create a file in _includes/custom/ called pagination. In that have your pagination code
<!-- This loops through the paginated posts -->
{% for post in paginator.posts %}
<h1>{{ post.title }}</h1>
<p class="author">
<span class="date">{{ post.date }}</span>
</p>
<div class="content">
{{ post.content }}
</div>
{% endfor %}
<!-- Pagination links -->
<div class="pagination">
{% if paginator.previous_page %}
Previous
{% else %}
<span class="previous">Previous</span>
{% endif %}
<span class="page_number ">Page: {{ paginator.page }} of {{ paginator.total_pages }}</span>
{% if paginator.next_page %}
Next
{% else %}
<span class="next ">Next</span>
{% endif %}
</div>
Now in your _layout/index.html add
{% if paginator.page != 1 %}
{% include custom/pagination %}
{% else %}
The original content of index
{% endif %}

Resources