My Views.py
context['user'] = User.objects.filter(code='01').values('name', 'phone')
print(context['user'])
The current results are as follows:
<QuerySet [{'name': 'John', 'cellphone': '1234567890'}, {'name': 'Doe', 'cellphone': '1234512345'}]>
How can I get a result like this from templates?
{% for u in user %}
<span>name :</span> <span> {{ u.name }} / </span>
<span>cellphone :</span> <span> {{ u.cellphone }}</span>
{% endfor %}
# want result
name : John, Doe / cellphone : 1234567890, 1234512345
Loop twice.
<span>name :</span>
{% for u in user %}
{% if not forloop.first %}, {% endif %}{{ u.name }}
{% endfor %}
<span> / cellphone :</span>
{% for u in user %}
{% if not forloop.first %}, {% endif %}{{ u.cellphone }}
{% endfor %}
Related
I'm trying to display "notes" in a nested list. Each note has a property called parentID that indicates a note that it is nested under.
Currently I am achieving a single level nest by doing this:
models.py
class Note(Model):
title = CharField()
tags = CharField()
content = TextField()
parentID = IntegerField(default=0)
class Meta:
database = db
app.py
def getSubnotes(note):
note_id = note.id
subnotes = models.Note.select().where(models.Note.parentID == note_id)
return subnotes
app.jinja_env.globals.update(getSubnotes=getSubnotes)
Index.html
<div class="row">
<div class="medium-12 medium-centered">
<ul>
{% for note in notes %}
{% if note.parentID == 0 %}
<li>{{ note.title }}</li>
<ul>
{% for subnote in getSubnotes(note) %}
<li>{{ subnote.title }}</li>
{% endfor %}
</ul>
{% endif %}
{% endfor %}
</ul>
</div>
I would like to, however, recursively find all children notes of a single note and list them out, so there are nests of nests.
I have seen this as an example of how to recursively list in jinja (from jinja docs):
<ul class="sitemap">
{%- for item in sitemap recursive %}
<li>{{ item.title }}
{%- if item.children -%}
<ul class="submenu">{{ loop(item.children) }}</ul>
{%- endif %}</li>
{%- endfor %}
</ul>
However I am confused about what .children actually is. How is it referencing itself or items of the same type?
How would I go about doing this recursively or is there a better method for achieving the same thing?
Any help is very much appreciated!
In the example from the docs, I think that item.children is just an iterable of items of the same type. Then {{ loop(item.children) }} causes the current loop to be executed over the iterable item.children creating a nested list.
You can verify this:
import jinja2
templ = """
{%- for item in items recursive %}
{{item.name}}
{%- if item.children %}
{{- loop(item.children) }}
{%- endif %}
{%- endfor %}
"""
items = [{'name': 'Bobby'},
{'name': 'Jack',
'children': [
{'name': 'Jake'},
{'name': 'Jill'}]},
{'name': 'Babby', 'children': []}]
template = jinja2.Template(templ)
print(template.render(items=items))
prints out
Bobby
Jack
Jake
Jill
Babby
So in your example, I think you should be able to do something like
<div class="row">
<div class="medium-12 medium-centered">
<ul>
{% for note in notes recursive %}
{% if note.parentID == 0 %}
<li>{{ note.title }}</li>
<ul>
{{ loop(getSubnotes(note)) }}
</ul>
{% endif %}
{% endfor %}
</ul>
</div>
as long as getSubnotes(note) returns empty if the note has no subNotes.
Even more complete, in my opinion (it explores lists and dictionaries inside lists):
<dl class="row">
{% for key, value in json.items() recursive %}
{% set outer_loop = loop %}
<dt class="col-3">{{ key }}</dt>
<dd class="col-9">
{% if value is string %}
{{ value }}
{% elif value is mapping %}
<dl class="row">
{{ loop(value.items()) }}
</dl>
{% elif value is iterable %}
<ol>
{% for item in value %}
<li>
{% if item is mapping %}
<dl class="row">
{{ outer_loop(item.items()) }}
</dl>
{% else %}
{{ item }}
{% endif %}
</li>
{% endfor %}
</ol>
{% else %}
{{ value }}
{% endif %}
</dd>
{% endfor %}
</dl>
I wonder if/how could be simplified.
I have a MenuSection model and a Product model. The Product model has MenuSection set as a ForeignKey. Everything works fine, except I am having difficulty figuring out how to query the Product model and listing out a list of objects unique to the ForeignKey, but print the ForeignKey value once at the top of the template.
Example of how I would like the Products printing to the template:
Salads (FK) <= Only printed once
Cobb (product.name)
Ceasar (product.name)
Pizza (FK)
Supreme (product.name)
Veggie (product.name)
...
Tag
#register.inclusion_tag('tags/_starters.html', takes_context=True)
def products(context):
product = Product.objects.all()
return {
'product': product,
'request': context['request'],
}
Tag Template
{% for p in product %}
<div class="menu-wrapper">
<div class="menu-description">
<h1>{{ p.section.name }}</h1> <======= This is the (FK) that I need to print once.
<div class="menu-list">
<h5>{{ p.name }}</h5>
<p class="price">
{% if p.price_b %}
{{ p.price_a }}/
{{ p.price_b }}
{% else %}
{{ p.price_a }}
{% endif %}
</p>
<span class="menu-dot-line"></span>
</div>
<p class="menu-ingredients">{{ p.description }}</p>
</div>
</div>
{% endfor %}
Model
#register_snippet
class Product(ClusterableModel):
section = models.ForeignKey(MenuSection, verbose_name='Menu Section')
name = models.CharField(max_length=255, verbose_name='Menu Item Name')
...
Instead of querying Product in your tag, return
return {
'menu_sections': MenuSection.objects.all()
}
Then, in your template,
{% for menu_section in menu_sections %}
{{ menu_section.name }}
{% for product in menu_section.product_set.all %}
{{ product.name }}
{% endfor %}
{% endfor %}
I am currently trying to fix an issue by using jinja variables, but somehow the variable does not keep the value outside the loop, even though I declared it before the loop begins:
{% set disablecounter = 0 %}
{% if disablecounter == 0 %}
{% for einzelroom in all_einzelzimmer %}
{% if zimmer.id == einzelroom.zimmer_id %}
{% set price = einzelroom.preis %}
<div class="preis-element">
<p class="preis"> <span class="smallab"> ab </span> {{ price|int }}€ </p>
</div>
{% set disablecounter = disablecounter + 1 %}
{{ disablecounter }}
{% endif %}
{% endfor %}
{% endif %}
{{ disablecounter }}
The variable is disablecounter inside the loop it is 1 but outside it is still 0
Thanks!
EDIT
Surrounding with a with statement also didnt worked:
{% with foo = 42 %}
{{ foo }}
{% endwith %}
{% with %}
{% set foo = 42 %}
{{ foo }}
{% endwith %}
I found a great solution here on SO by #Chris Warth.
Original answer by #Peter Hollingsworth:
https://stackoverflow.com/a/32700975/5291566
{% with disablecounter = [0] %}
{% if disablecounter == [0] %}
{% for einzelroom in all_einzelzimmer %}
{% if zimmer.id == einzelroom.zimmer_id %}
<div class="preis-element">
<p class="preis"> <span class="smallab"> ab </span> {{ einzelroom.preis|int }}€ </p>
</div>
{% if disablecounter.append(disablecounter.pop() + 1) %}{% endif %}
{% endif %}
{% endfor %}
{% endif %}
The dictionary I'm passing to the Django template contains 2 dictionaries, each with a list:
'nav_dict': {
'class_name': ['Chemical', 'Avian', 'Mammal'],
'tab_label': ['Chemical!', 'Avian!', 'Mammal!']
}
I want to loop over the lists in each dict to fill out this line of code:
<li class="{{ item_className }} tabSel">{{ item_tabLabel }}</li>
where item_className = each value in the class_name list and item_tabLabel = each value in the tab_label list. The result would 3 <li> tags with a class_name and tab_label.
I have tried something like this (This code only handles the class_name part), but I can't get the loops to append to the same line of code (each <li>):
{% for key, value in nav_dict.items %}
{% if key == 'class_name' %}
{% for item_className in value %}
{% if forloop.counter0 == 0 %}
<li class="{{ item_className }} tabSel">{{ item_tabLabel }}</li>
{% else %}
<li class="{{ item_className }} tabUnsel">{{ item_tabLabel }}</li>
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
The problem you have is with the way you are presenting your data.
Why don't you create your dictionary like this, where each key is the class name and the associated value is the label. It would be more semantic and readable.
'nav_dict': {
'Chemical': 'Chemical!',
'Avian': 'Avian!',
'Mammal': 'Mammal!,
}
Then you can just loop over this and place the key as the class attribute, and the value as the label attribute.
{% for key, value in nav_dict.items %}
{% if forloop.counter0 == 0 %}
<li class="{{ key }} tabSel">{{ value }}</li>
{% else %}
<li class="{{ key }} tabUnsel">{{ value }}</li>
{% endif %}
{% endfor %}
If the order of the elements is important (as dictionaries are un-ordered), you could use an OrderedDict from the collections module to retain insertion order. You would do something like this inside your view...
>>> from collections import OrderedDict
>>> nav_dict = OrderedDict(zip(['Chemical', 'Avian', 'Mamma!'], ['Chemical!', 'Avian!', 'Mammal!']))
OrderedDict([('Chemical', 'Chemical!'), ('Avian', 'Avian!'), ('Mammal', 'Mammal!')])
Similarly you could use a list of tuples as your data
'nav_list': [('Chemical', 'Chemical!'), ('Avian', 'Avian!'), ('Mammal', 'Mammal!')]
And loop over this object like so
{% for class_name, label_name in nav_list %}
{% if forloop.counter0 == 0 %}
<li class="{{ class_name }} tabSel">{{ label_name }}</li>
{% else %}
<li class="{{ class_name }} tabUnsel">{{ label_name }}</li>
{% endif %}
{% endfor %}
If you only want to append an exclamation mark to your string to create the label, you could of course create a custom template filter instead - or just append the exclamation mark inside the template itself.
If you have to use that dictionary, you can use this template code:
{% for item_className in nav_dict.class_name %}
{% with forloop.counter0 as index_className %}
{% for item_tabLabel in nav_dict.tab_label %}
{% with forloop.counter0 as index_tabLabel %}
{% ifequal index_className index_tabLabel %}
{% if index_className == 0 %}
<li class="{{ item_className }} tabSel">{{ item_tabLabel }}</li>
{% else %}
<li class="{{ item_className }} tabUnsel">{{ item_tabLabel }}</li>
{% endif %}
{% endifequal %}
{% endwith %}
{% endfor %}
{% endwith %}
{% endfor %}
I have a list of cities names that is variable and I want to break it into 4 columns evenly. I have some solution but it looks overwhelmed and dirty. What's the best and simplest way to do it?
My solution is here:
{% set cities_in_column = cities|length/4|int %}
{% set step=0 %}
<div class="four columns">
{% for city in cities|sort %}
{% if step > cities_in_column %}
{% set step = 0 %}
</div>
<div class="four columns">
{% endif %}
<h5>{{ city.name }} <span style="float:right;">({{ city.users_count }})</span></h5>
{% set step=step + 1 %}
{% endfor %}
</div>
You are looking for the slices filter:
{% for column in cities | sort | slice(4) -%}
<div class="four columns">
{%- for city in column -%}
<h5>{{ city.name }}
<span style="float:right;">({{ city.users_count }})</span></h5>
{%- endfor -%}
</div>
{%- endfor %}
There is also a complement to slices called batch that provides runs of n (rather than splitting up the iterable into n groups).
This is a job for CSS*:
<ol style="column-count: 4;">
{% for city in cities|sort %}
<li>
{{ city.name }} ({{ city.users_count }})
</li>
{% endfor %}
</ol>
(*Be it column-count, float, flex, etc..)