Looping Through JSON, List, List In List To Accodian Bootstrap - python

What It Looks Like Now(Image)
What I would like if for the episodes to append under each season. There are 7 lists in the episodes list, and 7 seasons in total, right now the whole episode list is printing into each season (can be seen in the picture provided), but I would like each list within the episode list of go under each season. Right now there are two episodes for each season so I would like there to be two episodes under each season, instead of all episodes under each season. This is done using the Bootstrap accordion. Thanks
<div id="accordion" role="tablist">
{% for season in tvdata[currentSeries]["seasons"] %}
<div class="card">
<div class="card-header" role="tab" id="heading">
<h5 class="mb-0">
<a data-toggle="collapse" href="#collapse" role="button" aria-expanded="false" aria-controls="collapse">
<p>Season {{ season }}</p>
</a>
</h5>
</div>
{% for season in tvdata[currentSeries]["episodes"] %}
{% for items in season %}
<div id="collapse" class="collapse show" role="tabpanel" aria-labelledby="heading" data-parent="#accordion">
<div class="card-body">
{{ items }}
</div>
</div>
{% endfor %}
{% endfor %}
</div>
{% endfor %}
</div>
JSON FILE:
"seasons": [1, 2, 3, 4, 5, 6, 7],
"episodes": [ ["S1-ep1","S1-ep2"],
["S2-ep1","S2-ep2"],
["S3-ep1","S3-ep2"],
["S4-ep1","S4-ep2"],
["S5-ep1","S5-ep2"],
["S6-ep1","S6-ep2"],
["S7-ep1","S7-ep2"]]
}
ISSUE Fixed (Thanks To Below):
<div id="collapse" class="collapse show" role="tabpanel" aria-labelledby="heading" data-parent="#accordion">
<div class="card-body">
{% for seasoneps in tvdata[currentSeries]["episodes"][season-1] %}
{% for eps in seasoneps %}
{{ eps }}
{% endfor %}
{% endfor %}
</div>
</div>

I havent used jinja - but used some knockout templating as well as looked into mustache and asp.net razor views - yours feels off to me:
You use two for-loops with the same variable seasons with the inner one overwriting the outer ones value - just guesstemating.
Please try:
<div id="accordion" role="tablist">
{% for season in tvdata[currentSeries]["seasons"] %}
<div class="card">
<div class="card-header" role="tab" id="heading">
<h5 class="mb-0">
<a data-toggle="collapse" href="#collapse" role="button" aria-expanded="false" aria-controls="collapse">
<p>Season {{ season }}</p>
</a>
</h5>
</div>
{% for items in tvdata[currentSeries]["episodes"][season-1] %}
<div id="collapse" class="collapse show" role="tabpanel" aria-labelledby="heading" data-parent="#accordion">
<div class="card-body">
{{ items }}
</div>
</div>
{% endfor %}
</div>
{% endfor %}
</div>
I am unsure about the [season-1] - part - might be you need to use [{{season}}-1] or whatever syntax lets you select the part of the json thats specific to that season (the 2 items inner list)

Related

Django - Iterating over list in template

Currently trying to iterate over a list using Django templating.
What I am trying to achieve is having multiple row with three columns. The current logic creates a one row with around every third card element.
What would be the best approach for creating each row w/ three columns?
{% extends "stockwatcher/base.html" %}
{% block content %}
<div class="container">
{% for stock in stocks %}
{% if forloop.counter0 == 0 or forloop.counter0|divisibleby:3 %}
<div class="row">
{% endif %}
<div class="col-sm">
<div class="card text-white bg-info mb-3" style="max-width: 18rem;">
<div class="card-header">{{stock.transaction_date}}</div>
<div class="card-body">
<h5 class="card-title">{{ stock.id }} {{stock.ticker}} </h5>
<p class="card-text">{{stock.senator}} - {{stock.type}}</p>
</div>
</div>
</div>
{% if forloop.counter0 == 0 or forloop.counter0|divisibleby:3 %}
</div>
{% endif %}
{% endfor %}
</div>
{% endblock content %}
You should use row div outside the for loop and bootstrap classes will handle the rest for you. You can also use {% empty %} tag to handle empty list.
{% extends "stockwatcher/base.html" %}
{% block content %}
<div class="container">
<div class="row">
{% for stock in stocks %}
<div class="col-sm">
<div class="card text-white bg-info mb-3" style="max-width: 18rem;">
<div class="card-header">{{stock.transaction_date}}</div>
<div class="card-body">
<h5 class="card-title">{{ stock.id }} {{stock.ticker}} </h5>
<p class="card-text">{{stock.senator}} - {{stock.type}}</p>
</div>
</div>
</div>
{% empty %}
No items
{% endfor %}
</div>
</div>
{% endblock content %}

How do I use variables as selectors in HMTL/ Bootstrap4?

I'm trying to make a for loop to build an accordion in Bootstrap, but every time I click the button to expand/ collapse a card, every card expands/ collapses. I think this is due to a shared id across all cards, so I want to use the post title as the id selector for each card. Here is the code I currently have:
{% for post in blog_posts %}
<div id="accordion">
<div class="card">
<h3 class="card-header" id="header">
<button class="btn btn-info" data-toggle="collapse"
data-target="#body" aria-expanded="false"
aria-controls="post: ">
{{ post.title }}
<small><p>Posted by {{ post.author }} on
{{ post.date_added|date:'D M d, Y H:i' }}</p></small>
</button>
</h3>
<div id="body" class="collapse show" aria-labelledby="header"
data-parent="#accordion">
<div class="card-body">
{{ post.text|linebreaks }}
<small>
<a class="text-dark" href="{% url 'blogs:edit_post' post.id %}">
edit post</a>
</small>
</div>
</div>
</div>
{% empty %}
<p>There are no posts to display.</p>
{% endfor %}
I've tried changing the h3 id to {{ post.title }}, but that doesn't seem to work. Any help is much appreciated.
Example code:
https://getbootstrap.com/docs/4.0/components/collapse/#accordion-example
You need the id's to be unique for each accordion section (otherwise they will all open at once), you could use the post.id for that.
{% if blog_posts %}
<div id="accordion">
{% for post in blog_posts %}
<div class="card">
<h3 class="card-header" id="header-{{post.id}}">
<button class="btn btn-info" data-toggle="collapse"
data-target="#post-{{post.id}}" aria-expanded="false"
aria-controls="post-{{post.id}}">
{{ post.title }}
<small><p>Posted by {{ post.author }} on
{{ post.date_added|date:'D M d, Y H:i' }}</p></small>
</button>
</h3>
<div id="post-{{post.id}}" class="collapse show" aria-labelledby="header-{{post.id}}"
data-parent="#accordion">
<div class="card-body">
{{ post.text|linebreaks }}
<small>
<a class="text-dark" href="{% url 'blogs:edit_post' post.id %}">
edit post</a>
</small>
</div>
</div>
{% endfor %}
</div>
{% else %}
<p>There are no posts to display.</p>
{% endif %}

Django/Bootstrap 4: How to align elements inside of multiple parent divs

So I am developing a website and for the life of me I can't figure out how to align the description, price, stock and add cart button in multiple versions of the same <div>. I know it is to do with the size of the image I am using but I'm not sure how to fix this.
Here is a diagram of how I want it to look:
But when I apply a 'h-100' class to the card <div> this is what happens:
I want the images to keep their positions but for the descriptions, add cart button and price/stock to all be horizontally aligned, as well as the height of the overall cards to be the same.
Here is my Django template code:
{% extends 'base.html' %}
{% block content %}
<div class="container-fluid">
<div class="jumbotron">
<h2>Welcome to MyTea</h4>
<p>Here we have teas of all varieties from all around the globe</p>
</div>
<div class="row">
<div class="col-sm-3">
<h4>Categories</h4>
<ul class="list-group">
All Categories
{% for c in countcat %}
<a href="{{ c.get_absolute_url }}" class="list-group-item catheight">{{c.name}}
<span class="badge badge-light">{{c.num_products}}</span>
</a>
{% endfor %}
</ul>
</div>
<div class="col-sm-9">
{% for product in products %}
{% if forloop.first %}<div class="row">{% endif %}
<div class="col-sm-6">
<div class="card border-primary mt-3 h-100">
<div class="card-header"><h3>{{product.name}}</h3></div>
<div class="card-body">
{% if product.image %}
<div class="h">
<img src="{{product.image.url}}" class="img-fluid">
</div>
{% endif %}
<p class="bg-light font-weight-light ">{{product.description}}</p>
{% if product.stock > 0 %}
<a href="{% url 'add_cart' product.id %}" type="button" class="btn btn-primary btn-sm mb-2">
<p class="m-0">Add to cart</p>
</a>
{% else %}
<a href="#" type="button "class="btn btn-danger btn-sm mb-2">
<p class="m-0">Out of stock</p>
</a>
{% endif %}
<div class="card-footer">
<p>Price: €{{product.price}}</p>
<p>Stock left: {{product.stock}}</p>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% endblock content %}
Thanks for any help
The code can be corrected with a simple re-alignment of the content inside .card and correctly closing </div> statements.
Remove {% if forloop.first %}<div class="row">{% endif %} statement and place <div class="row"> above the for loop.
Add to cart and Out of stock buttons should be placed inside .card-footer and .card-body should be closed appropriately. This will leave the image and description within .card-body
Make sure h-100 class is added to `.card'.
Might I suggest adding end of div comments to all the div statements. The code is readable better in this way and helps in mitigating missing or misplaced </div> statements.
{% extends 'base.html' %}
{% block content %}
<div class="container-fluid">
<div class="jumbotron">
<h2>Welcome to MyTea</h4>
<p>Here we have teas of all varieties from all around the globe</p>
</div>
<!-- .jumbotron -->
<div class="row">
<div class="col-sm-3">
<h4>Categories</h4>
<ul class="list-group">
All Categories
{% for c in countcat %}
<a href="{{ c.get_absolute_url }}" class="list-group-item catheight">{{c.name}}
<span class="badge badge-light">{{c.num_products}}</span>
</a>
{% endfor %}
</ul>
</div>
<!-- .col-sm-3 -->
<div class="col-sm-9">
<div class="row">
{% for product in products %}
<div class="col-sm-6">
<div class="card border-primary mt-3 h-100">
<div class="card-header">
<h3>{{product.name}}</h3>
</div>
<!-- .card-header -->
<div class="card-body">
{% if product.image %}
<div class="h">
<img src="{{product.image.url}}" class="img-fluid">
</div>
<!-- .h -->
{% endif %}
<p class="bg-light font-weight-light ">{{product.description}}</p>
</div>
<!-- .card-body -->
<div class="card-footer">
{% if product.stock > 0 %}
<a href="{% url 'add_cart' product.id %}" type="button" class="btn btn-primary btn-sm mb-2">
<p class="m-0">Add to cart</p>
</a>
{% else %}
<a href="#" type="button " class="btn btn-danger btn-sm mb-2">
<p class="m-0">Out of stock</p>
</a>
{% endif %}
<p>Price: €{{product.price}}</p>
<p>Stock left: {{product.stock}}</p>
</div>
<!-- .card-footer -->
</div>
<!-- .card -->
</div>
<!-- . col-sm-6 -->
{% endfor %}
</div>
<!-- .row -->
</div>
<!-- .col-sm-9 -->
</div>
<!-- .row -->
</div>
<!-- .container-fluid -->
{% endblock content %}

Dynamic html attribute naming

I have a list of banking transactions that I'm listing. I'm currently using bootstrap for my HTML/CSS. I found some template code that works well enough for what I want to do, but I've run into a problem: there's no way to know the id of the collapsing div element for the parent element. It's easier to see the html than to explain:
{% for key, value in transactions.items %}
<div id="accordion">
<div class="card">
<div class="card-header" id="heading-1">
<h5 class="mb-0">
<a role="button" data-toggle="collapse" href="#whatid" aria-expanded="true" aria-controls="whatid">
{{ key }}
</a>
</h5>
</div>
{% for key2, value2 in value.items %}
<div id="whatid" class="collapse show" data-parent="#accordion" aria-labelledby="heading-1">
<div class="card-body">
<div id="accordion-1">
<div class="card">
<div class="card-header" id="heading-1-1">
<h5 class="mb-0">
<a class="collapsed" role="button" data-toggle="collapse" href="#collapse-1-1" aria-expanded="false" aria-controls="collapse-1-1">
{{ key2 }}
</a>
</h5>
</div>
{% for tr in value2 %}
<div id="collapse-1-1">{{ tr.description }}</div>
{% endfor %}
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endfor %}
The attributes href, id and most importantly aria-controls of the child div element can't be known ahead of time and therefore won't be correctly associated with the button click. Is it possible to do this? It's a bit of a chicken before the egg problem, so I don't really know what there is to do.

how to change batch argument dynamically in jinja template depending on device size

I have the below bootstrap panels, three col-xs-4 per row rendered in a jinja template, and it looks super nice on a desktop.
but when trying smaller devices it get ugly. so I want to know if there is a way to change the batch argument to 1 per row under a certain device size ?
or maybe there is a better approach, I'm very open as I'm very new to this :)
<div class="container-fluid">
{% for raceorganizers in res.keys() | batch(3, ' ') %}
<div class="row">
{% for raceorganizer in raceorganizers %}
<div class="col-xs-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{{ raceorganizer.name }}<span
class="text-right pull-right flag-icon flag-icon-{{ raceorganizer.country_code }}"></span>
</h3>
</div>
<div class="panel-body panel-image">
<img class="panel-image-preview"
src="{{ url_for('static', filename='img/full/' + im ) }}" alt='{{ im }}'>
</div>
<div class="panel-footer">
{% for race in res[raceorganizer] %}
<ul class="list-unstyled">
<li>
<span class="glyphicon glyphicon-road"></span>
<span class="badge">{{ '{:.1f}'.format(race.distance_number) }}</span>
<span class="flaticon-mountain40"></span>
<span class="badge">{{ '{:.0f}'.format(race.elevation_number) if race.elevation_number is not none else '-' }}</span>
</li>
</ul>
{% endfor %}
</div>
</div>
</div>
{% endfor %}
</div>
{% endfor %}
</div>
If you look more closely at bootstrap's grid system, you could completely get rid of the batch call. If you play with different tiers of classes (col-xs for phones+, col-md for desktops+) on the same element, you will be able to get bootstrap to split the content into 3 columns on desktops and 1 on smaller screens.

Categories

Resources