Why doesn't Django recognize this in the template - python

I'd like to show my top level categories if the parent is equal to one. The topcats is a queryset that contains category items. However the code starred below is not working. It is not finding any cat items with parent = 1. Any idea why?
{% for cat in topcats %}
**{% if cat.parent == 1 %}**
<h3>{{ cat.category }}</h3>
{% for each in topcats %}
{% if each.parent == cat.id %}
<h5>{{ each }}</h5>
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
Note: parent is a TreeForeignKey in the database

I'd say cat.parent is a model object.
This should work for you:
{% if cat.parent.pk == 1 %}
However, this is quite hackish, as the parent node's id does not necessarily have a value of 1. The is_root_node() method is a better approach:
{% if cat.parent.is_root_node %}

Related

Django Template For Loop - reverese last two iterations

I am using Django 1.10 and Python 3.5.
I have been given some code that consists of a for loop that returns 3 iterations of value in alphabetical order.
For example the for loop returns: Chronological, Combination, Functional.
However I need the for loop to return: Chronological, Functional, Combination (the last two iterations/values are reversed). I am forced to keep the for loop.
Is this at all possible with a for loop?
I have tried combining {% if forloop.last %} with {% if forloop.first%} and also setting the value with {% if forloop.counter == 2 %}...set value to Functional...{% endif %} and {% if forloop.counter == 3 %}...set value to Combination...{% endif %} but I cannot get this to achieve what I want.
Here is my code:
{% for resume_format_image in resume_format_images %}
<div class="col-md-4">
{% with "resumes/resume_format_description_"|add:resume_format_image.style.lower|add:".html" as template_name %}
{% include template_name %}
{% endwith %}
</div>
{% endfor %}
I just figured this out:
{% for resume_format_image in resume_format_images %}
<div class="col-md-4">
{% if forloop.first%}
{% include "resumes/resume_format_description_chronological.html" %}
{% elif forloop.last%}
{% include "resumes/resume_format_description_combination.html" %}
{% else %}
{% include "resumes/resume_format_description_functional.html" %}
{% endif %}
</div>
{% endfor %}
I hope this helps someone.

How to count authors in Pelican Blogs?

I was trying to make my blog show "Authors" instead of "Author" when there are more than 1 authors for the same article.
The solution (thanks to #Avaris) is to set i = article.authors|count and that can be used as follows
<div align="right">
{% set i = article.authors|count %}
{% if i != 1 %}
Authors:<br>
{% endif %}
{% if i == 1 %}
Author:<br>
{% endif %}
{% if article.authors %}
{% for author in article.authors %}
{{ author }}<br>
{% endfor %}
{% endif %}
</div>
This is different to Set variable in jinja because in Pelican I cannot find a command like lenght(authors) to obtain a number to define a condition.

Django {% blocktrans %}: How to handle pluralization inside a for loop?

I have the following loop in my Django template:
{% for item in state.list %}
<div> HTML (CUSTOMERS BY STATE) </div>
<!-- print sum of customers at bottom of list -->
{% if forloop.last %}
<h4>{{ forloop.counter }} Valued Customers</h4>
{% endif %}
{% endfor %}
Obviously, if I end up with only one customer, I'd like to print singular "Valued Customer"
According to Django's docs, one should use blocktrans. Tried the following, a few flavors of nesting:
{% blocktrans count %}
{% if forloop.last %}
<h4>
{{ forloop.counter }}
Valued Customer
{% plural %}
Valued Customers
</h4>
{% endif %}
{% endblocktrans %}
Keep getting TemplateSyntaxError: Invalid block tag: 'blocktrans', expected 'empty' or 'endfor'
Is there no way to combine with another loop? Any ideas how to solve? Thanks!
Here is the working code, thanks to alko:
{% load i18n %}
<!-- ... -->
{% if forloop.last %}
<h4>
{{ forloop.counter }}
{% blocktrans count count=forloop.counter %}
Valued Customer
{% plural %}
Valued Customers
{% endblocktrans %}
</h4>
{% endif %}
Probably, you forgot to load translation tags. Add following line at the top of your template:
{% load i18n %}
After you fix that, note that for a blocktrans tag after count a variable, whose value will serve for plural detection, should be specified, so you probably need something like
{% blocktrans count count=forloop.counter %}
To pluralize use this:
Customer{{ forloop.counter|pluralize }}

Does Jinja2 support nested if statements?

I read the docs and I am not clear on this is right at all. I know you can use nested for loops, but if statements seem to be different.
Can i do the following?
{% if thing=true %}
<div> something here</div>
{% if diffthing=true %}
<div> something else</div>
{% else %}
<div> third thing</div>
{% endif %}
{% else %}
<div> nothing here </div>
{% endif %}
Or should the format be different somehow?
Jinja2 supports nested blocks, including if statements and other control structures.
See the documentation on Block Nesting and Scope: "Blocks can be nested for more complex layouts."
A good use case for this is writing macros that conditionally output HTML:
{# A macro that generates a list of errors coming back from wtforms's validate function #}
{% macro form_error_summary(form, li_class='bg-danger') %}
{# only do the following on error... #}
{% if form.errors %}
<ul class="errors">
{# you can do layers of nesting as needed to render your content #}
{% for _field in form %}
{% if _field.errors %}
{% for error in _field.errors %}
<li class={{li_class}}>{{_field.label}}: {{ error|e }}</li>
{% endfor %}
{% endif %}
{% endfor %}
</ul>
{% endif %}
{% endmacro %}
The answer is yes.
I'm using logic very similar to yours in a live application and the nested if blocks work as expected. It can get a little confusing if you don't keep your code clean, but it works fine.
It seem possible. Refer to the documentation here: http://jinja.pocoo.org/docs/templates/#if
Just a quick add, if you're unpacking data to populate your fields, Jinja will only unpack it once. I had a similar problem with MongoDB and found if you change the item to a list item you iterate through it more than once without nesting
#app.route("/")
#app.route("/get_shrink")
def get_shrink():
# find and sort shrink top 5
shrink = list(mongo.db.shrinkDB.find().limit(5).sort(
"amount_lost_value", -1,))
return render_template(
"shrink.html", shrinkDB=shrink)
{% for shrink in shrinkDB %}
{% if shrink.resolved == true %}
<li>{{ shrink.product_name }} ||£ {{ shrink.amount_lost_value }} || {{ shrink.date }}</li>
{% endif %}
{% endfor %}
</span>
</div>
</div>
<div class="col s12 m5 offset-m2">
<h4>Top 5 Resolved Threats</h4>
<div class="card-panel light-blue">
<span class="white-text">
<!-- Shrink For loop top 5 resolves-->
{% for shrink in shrinkDB %}
{% if shrink.resolved != true %}
<li>{{ shrink.product_name }} ||£ {{shrink.amount_lost_value }} || {{ shrink.date }}</li>
{% endif %}
{% endfor %}

Django if statement not working

{% extends "base.html" %}
{% block content %}
<h1>{{ page }}</h1>
{% for category in categories %}
{% if category.page == page %}
<h2>{{ category.title }}!</h2>
{% for item in categoryitems %}
{{ category.title }} {{ item.category }}
{% if item.category == category.title %}
<h3>{{ item.title }}</h3>
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% endblock %}
The first statement if category.page == page is working fine, but the other one - if item.category == category.title - doesn't, for the sake of checking if everything is fine I've also added those {{category.title}} and {{item.category}} outputs and they are identical, so why doesn't the loop show me my item.title ? Without the if, it works, but, of course, shows every element in the list, which is smthn I don't need.
Do not depend on the page output to tell you what is correct, since the output is dependent on the code. Instead, do it correctly in the first place.
{% if item.category == category %}

Categories

Resources