Jinja template groupby sorting issue - python

In this code block, I have grouped by headings. But I want to sort the titles in array index order. Not alphabetically.
{% set list = widget.attributes.faq_item %}
{% for title_group in list|groupby('value.main_title') %}
<h2 class="account-sss__title">{{title_group.grouper}}</h2>
{% for item in title_group.list %}
<a href="#" class="account-sss__list--link js-link">
{{item.value.question}}
</a>
<div class="account-sss__content js-account-sss__content">
{{item.value.answer}}
</div>
{% endfor %}
{% endfor %}

I solved the problem.
{% set list = widget.attributes.faq_item %}
{% set Arr_titles = [] %}
{% for event in list %}
{% if event.value.main_title not in Arr_titles %}
{% do Arr_titles.append(event.value.main_title) %}
{% endif %}
{% endfor %}
{% for index in Arr_titles %}
<h2 class="account-sss__title">{{index}}</h2>
{% for item in list %}
{% if index == item.value.main_title %}
<a href="#" class="account-sss__list--link js-link">
{{item.value.question}}
</a>
<div class="account-sss__content js-account-sss__content">
{{item.value.answer}}
</div>
{% endif %}
{% endfor %}
{% endfor %}

Related

Django python pagination always displaye the first 2, and last 2 pages

I have some pagination for a table. I have it so that it will only show 3 pages either side of the current page. However if I am on the 5th page, The first page disappears. I am trying to set it up so that the first two and last two pages of the pagination are always visible regardless of what the current page is.
code:
{% if is_paginated %}
<div class="pagination">
{% if current_page.has_previous %}
<a class="page-link" style="font-size: 24px; padding: 2px;" href="?page={{ current_page.previous_page_number }}">«</a>
{% else %}
<a class="page-link" style="font-size: 24px; padding: 2px;" href="">«</a>
{% endif %}
{% for i in current_page.paginator.page_range %}
{% if i == 1 %}
{% if current_page.number == i %}
<a class="page-link active" href="">{{ i }}</a>
{% else %}
<a class="page-link" href="?page={{ i }}">{{ i }}</a>
{% endif %}
{% endif %}
{% if i == 2 %}
{% if current_page.number == i %}
<a class="page-link active" href="">{{ i }}</a>
{% else %}
<a class="page-link" href="?page={{ i }}">{{ i }}</a>
{% endif %}
{% endif %}
{% if i != 1 and i != 2 %}
{% if current_page.number == i %}
<a class="page-link active" href="">{{ i }}</a>
{% else %}
{% if current_page.number|add:-4 == i %}
<a class="page-link" href="">...</a>
{% endif %}
{% if current_page.number|add:3 >= i and current_page.number|add:-3 <= i %}
<a class="page-link" href="?page={{ i }}">{{ i }}</a>
{% endif %}
{% if current_page.number|add:4 == i %}
<a class="page-link" href="">...</a>
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% if current_page.has_next %}
<a class="page-link" style="font-size: 24px; padding: 2px;" href="?page={{ current_page.next_page_number }}">»</a>
{% else %}
<a class="page-link" style="font-size: 24px; padding: 2px;" href="">»</a>
{% endif %}
</div>
{% endif %}
Screenshot:
Update:
I have worked out a jank way of having the first two pages always showing but cannot get the last two pages to always show
I add some well place if statements to always display the first and last place.
I set it so that if i == 1 show the page in the pagination navbar. Then during the loop of i I remove the first page and last page using i != 1 and i != current_page.paginator.page_range|last.
Using current_page.paginator.page_range|last will get the last value in the range and then you do the same for the last page as you did for the first page.
Code:
{% for i in current_page.paginator.page_range %}
{% if i == 1 %}
{% if current_page.number == i %}
<a class="page-link active" href="">{{ i }}</a>
{% else %}
<a class="page-link" href="?page={{ i }}">{{ i }}</a>
{% endif %}
{% endif %}
{% if i != 1 and i != current_page.paginator.page_range|last %}
{% if current_page.number == i %}
<a class="page-link active" href="">{{ i }}</a>
{% else %}
{% if current_page.number|add:-4 == i %}
<a class="page-link" href="">...</a>
{% endif %}
{% if current_page.number|add:3 >= i and current_page.number|add:-3 <= i %}
<a class="page-link" href="?page={{ i }}">{{ i }}</a>
{% endif %}
{% if current_page.number|add:4 == i %}
<a class="page-link" href="">...</a>
{% endif %}
{% endif %}
{% endif %}
{% if i == current_page.paginator.page_range|last %}
{% if current_page.number == i %}
<a class="page-link active" href="">{{ current_page.paginator.page_range|last }}</a>
{% else %}
<a class="page-link" href="?page={{ current_page.paginator.page_range|last }}">{{ current_page.paginator.page_range|last }}</a>
{% endif %}
{% endif %}
{% endfor %}
Screenshot:

display list in django template

I have a list of tuples which looks something like the following:
answer_guess_list = [('A',), ('B', 'C',), ('A', 'B', 'C', 'D',)]
In my templates, I have a template variable with the same name.
{% for guess_list in answer_guess_list %}
<p>
{% for guess_value in guess_list %}
{{ guess_value }}, # Notice the comma (,)
{% endfor %}
</p>
{% empty %}
<p>Nothing to show.</p>
{% endfor %}
It displays the list as the following:
A,
B, C,
A, B, C, D,
I don't want the terminal commas and rather display it as:
A
B, C
A, B, C, D
I do not know how to achieve that.
Could you help please?
This would be one way to do it:
{% for guess_list in answer_guess_list %}
<p>
{% for guess_value in guess_list %}
{{ guess_value }}{% if forloop.counter < guess_list|length %}, {% endif %}
{% endfor %}
</p>
{% empty %}
<p>Nothing to show.</p>
{% endfor %}
Or you could also use the built-in template filter join:
{% for guess_list in answer_guess_list %}
<p>
{{ guess_list|join:", " }}
</p>
{% empty %}
<p>Nothing to show.</p>
{% endfor %}
Here is the documentation for the template tags, the below is the tag it self.
#register.filter(name="my_filter")
def fltr(tpl):
return ','.join([str(i) for i in tpl])
After registering this tag by following instructions at the docs, you can use it as:
<p>
{% for guess_value in guess_list %}
{{ guess_value|my_filter }},
{% endfor %}
</p>
There's a built-in option for this in for templatetag called foorloop.last. Simply change your code to this:
{% for guess_list in answer_guess_list %}
<p>
{% for guess_value in guess_list %}
{{ guess_value }}{% if not forloop.last %},{% endif %}
{% endfor %}
</p>
{% empty %}
<p>Nothing to show.</p>
{% endfor %}
and if for loop is last, trailing comma won't render.

Looping over items with Jinja, adding in div after every 5th item

Problem
I have a list of 100 golf courses and I'm looking to insert a div, containing an image for an ad after every fifth course. How would I go about doing this?
Update #1
content.html (Revised, newest version)
I've updated my original code snippet because off of leovp's
suggested edited below. I'm having trouble showing only {% if content.featured == "Test" %} and wondering how I should closing my if-else statement.
{% for content in COPY.courses %}
<div class="course course--featured">
<img src="" class="course__image image--region">
<div class="course__inner">
<div class="course__wrapper">
{% if content.state == "MO" %}
<p class="course__state">Missouri</p>
{% elif content.state == "IL" %}
<p class="course__state">Missouri</p>
{% endif %}
</div>
<div class="course__wrapper">
<p class="course__name name--region">{{ content.name }}</p>
</div>
<p class="course__desc">{{ content.description }}</p>
</div>
</div>
{% if loop.index % 5 == 0 %}
<div class="advertising advertising--inline">
<div class="ad ad--rect">
<div class="text-center hidden-xs">
<div id="fixed-leaderboard-region-top"
class="dfp-ad"
data-dfp-custom-pos="fixed-leaderboard-top, htf"
data-dfp-size="[728,90]">
</div>
</div>
<div class="text-center hidden-sm hidden-md hidden-lg">
<div id="fixed-leaderboard-region-top-mobile"
class="dfp-ad"
data-dfp-custom-pos="fixed-leaderboard-top, htf"
data-dfp-size="[320,50]">
</div>
</div>
</div>
</div>
{% endif %}
{% endfor %}
</div>
content.html (Previous, old version for comparision)
I've looked into using batch from this Stack Overflow question that seemed similar, but I'm unsure if this solves my problem?
{% for content in COPY.courses %}
{% if content.featured == "Test" %}
<div class="course__inner">
<div class="course__wrapper">
{% if content.state == "MO"%}
<p class="course__state">Missouri</p>
{% elif content.state == "IL" %}
<p class="course__state">Illinois</p>
{% endif %}
</div>
<div class="course__wrapper">
<p class="course__name name--home">{{ content.name }}</p>
</div>
<p class="course__desc">{{ content.description }}</p>
</div>
{% endif %}
{% endfor %}
While iterating, you can get the current index and check if it's divisible by 5:
{% set count = 0 %}
{% for content in COPY.courses %}
{% if content.featured == "Test" %}
<div class="course course--featured">
<img src="" class="course__image image--home">
[...]
</div>
</div>
{% set count = count + 1 %}
{% if count % 5 == 0 %}
<!-- additional content once every 5 courses -->
{% endif %}
{% endif %}
{% endfor %}
NOTE: This approach no longer works after version 2.10.
For detail see:
How to increment a variable on a for loop in jinja template?

divide a categorized list into parts in django template

I have this model:
class Event_Category(models.Model):
event=models.ForeignKey(Event,related_name='event_category')
category=models.ForeignKey(Category,related_name='events')
user=models.ForeignKey(User)
in the view:
magazie_cats=Event_Category.objects.filter(event=instance).order_by('category').distinct()
return render_to_response('CompanyHub/Company/index.html', {'magazie_cats':magazie_cats},context_instance=RequestContext(request))
in the template:
{% regroup magazie_cats by category as service_list %}
I want to divide this categorized list into 3 parts and iterate over it. I tried to access each category by variable indexes:
{% for i in range(0,3) %}
{% for item in service_list.i.list %}
{{item.event.title}}
{% endfor %}
{% endfor %}
{% for i in range(3,6) %}
{% for item in service_list.i.list %}
{{item.event.title}}
{% endfor %}
{% endfor %}
{% for i in range(6,9) %}
{% for item in service_list.i.list %}
{{item.event.title}}
{% endfor %}
{% endfor %}
NOTE: the range for each loop is calculated by some custom filters based on service_list length . I didn't include the complete code to avoid complexity.
The problem is that the list variable index doesn't work and I don't know what to do.
You want to use the slice filter:
{% regroup magazie_cats by category as service_list %}
{% for cat in service_list|slice:":3" %}
{% for item in cat.list %}
{{item.event.title}}
{% endfor %}
{% endfor %}
{% for cat in service_list|slice:"3:6" %}
{% for item in cat.list %}
{{item.event.title}}
{% endfor %}
{% endfor %}
{% for cat in service_list|slice:"6:9" %}
{% for item in cat.list %}
{{item.event.title}}
{% endfor %}
{% endfor %}

How to increment a variable on a for loop in jinja template?

I would like to do something like:
variable p is from test.py which is a list ['a','b','c','d']
{% for i in p %}
{{variable++}}
{{variable}}
result output is:
1 2 3 4
You could use loop.index:
{% for i in p %}
{{ loop.index }}
{% endfor %}
Check the template designer documentation.
In more recent versions, due to scoping rules, the following would not work:
{% set count = 1 %}
{% for i in p %}
{{ count }}
{% set count = count + 1 %}
{% endfor %}
After 2.10, to solve the scope problem, you can do something like this:
{% set count = namespace(value=0) %}
{% for i in p %}
{{ count.value }}
{% set count.value = count.value + 1 %}
{% endfor %}
As Jeroen says there are scoping issues: if you set 'count' outside the loop, you can't modify it inside the loop.
You can defeat this behavior by using an object rather than a scalar for 'count':
{% set count = [1] %}
You can now manipulate count inside a forloop or even an %include%. Here's how I increment count (yes, it's kludgy but oh well):
{% if count.append(count.pop() + 1) %}{% endif %} {# increment count by 1 #}
Or...
{% set count = [] %}
{% for something-that-loops %}
{% set __ = count.append(1) %}
<div> Lorem ipsum meepzip dolor...
{{ count|length }}
</div>
{% endfor %}
(From comments by #eyettea and #PYB)
Here's my solution:
Put all the counters in a dictionary:
{% set counter = {
'counter1': 0,
'counter2': 0,
'etc': 0,
} %}
Define a macro to increment them easily:
{% macro increment(dct, key, inc=1)%}
{% if dct.update({key: dct[key] + inc}) %} {% endif %}
{% endmacro %}
Now, whenever you want to increment the 'counter1' counter, just do:
{{ increment(counter, 'counter1') }}
if anyone want to add a value inside loop then you can use this its working 100%
{% set ftotal= {'total': 0} %}
{%- for pe in payment_entry -%}
{% if ftotal.update({'total': ftotal.total + 5}) %}{% endif %}
{%- endfor -%}
{{ftotal.total}}
output = 5
Came searching for Django's way of doing this and found this post. Maybe someone else need the django solution who come here.
{% for item in item_list %}
{{ forloop.counter }} {# starting index 1 #}
{{ forloop.counter0 }} {# starting index 0 #}
{# do your stuff #}
{% endfor %}
Read more here:
https://docs.djangoproject.com/en/1.11/ref/templates/builtins/
I was struggle with this behavior too. I wanted to change div class in jinja based on counter. I was surprised that pythonic way did not work. Following code was reseting my counter on each iteration, so I had only red class.
{% if sloupec3: %}
{% set counter = 1 %}
{% for row in sloupec3: %}
{% if counter == 3 %}
{% set counter = 1 %}
{% endif %}
{% if counter == 1: %}
<div class="red"> some red div </div>
{% endif %}
{% if counter == 2: %}
<div class="gray"> some gray div </div>
{% endif %}
{% set counter = counter + 1 %}
{% endfor %}
{% endif %}
I used loop.index like this and it works:
{% if sloupec3: %}
{% for row in sloupec3: %}
{% if loop.index % 2 == 1: %}
<div class="red"> some red div </div>
{% endif %}
{% if loop.index % 2 == 0: %}
<div class="gray"> some gray div </div>
{% endif %}
{% endfor %}
{% endif %}
Just to shed more light into this problem.
Jinja2 variables behaves differently from that of conventional scripting languages, you can't modify the variable in a for loop.Hence to bypass this behaviour you can use a dictionary, since you can change the value of the dictionary.
**{% set margin={"margin_value":0} %}**
{% for lang in language %}
<ul>
<li style="margin-right: {{ margin.margin_value}}px">{{ lang }}</li>
</ul>
**{% if margin.update({"margin_value":margin.margin_value + 2}) %}
{% endif %}**
{% endfor %}
In the above code the value of the dictionary is being modified.

Categories

Resources