loop.last in jinja2 not working properly in django - python

guys I am trying to avoid printing two divs in my table in the last iteration of the loop of my Django template. I have used loop.last variable to check if the loop is in its last iteration, but it is not working for some reason. Here program session is simply a range(number_of_iterations_required).
Here is my code:
{% for n in program_sessions %}
<!-- 1st session start -->
<tr class="mb-2">
<td class="border border-0">
<div class="row">
<div class="col-6 mx-0 px-0">
<span class="float-end">Row: </span>
</div>
<div class="col-6 mx-0 px-0">
<span class="text-white">{{program.workout_time}}m</span>
</div>
{% if not loop.last %}
<div class="col-6 mx-0 px-0">
<span class="float-end">Rest: </span>
</div>
<div class="col-6 mx-0 px-0">
<span class="text-white">{{program.rest_time}}min</span>
</div>
{% else %}
<div class="col-6 mx-0 px-0">
<span class="float-end">Last Iteration boii! </span>
</div>
{% endif %}
</div>
</td>
</tr>
<!-- 1st session ends -->
{% endfor %}
</tbody>
</table>
</div>
Thank you in advance for your help.
Have a good day.

Looks like the syntax is not right. Try to change it to forloop instead of loop. You can have a look at the django docs for more info
{% if not forloop.last %}

Related

custom message if there isnt any record to show in django-template

Hello there im trying to show a custom message like "Doesnt exists" if there isnt really any record to show
and ignore having None in the template for empty records
Template :
<div class="col-md-6 col-sm-12 col-xs-12 form-group pull-right ">
<label style="color : blue;" class="control-label col-md-5 col-sm-3 col-xs-12 pull-right size_Style"><i class="fa fa-circle" style="color : blue;" aria-hidden="true"></i> knowledge cost :</label>
<span class="col-md-12 col-sm-12 col-xs-12 form-group pull-right colorfull">
{{ special_knowledge.knowledgecost|safe }}
</span>
</div>
<div class="col-md-6 col-sm-12 col-xs-12 form-group pull-right ">
<label style="color : blue;" class="control-label col-md-5 col-sm-3 col-xs-12 pull-right size_Style"><i class="fa fa-circle" style="color : blue;" aria-hidden="true"></i> knowledge cost percemtage :</label>
<span class="col-md-12 col-sm-12 col-xs-12 form-group pull-right colorfull">
{{ special_knowledge.knowledgecost_percent }}
</span>
</div>
based on the given HTML the first Field would Be None becuase i dont have any record for it in my db
, so is there any more efficient way than using if for each record ?
i tried this method for all to handle any empty record
{% if special_knowledge.knowledgecost %}
{{ special_knowledge.knowledgecost|safe }}
{% else %}
Doesnt exist
{% endif %}
You can try to use Django's built-in default_if_none filter for this.
E.g:
{{ special_knowledge.knowledgecost|default_if_none:"nothing" }}
First of: you could also use (Read more)
{% if special_knowledge.knowledgecost %}
{{ special_knowledge.knowledgecost|safe }}
{% empty %}
Doesnt exist
{% endif %}
But that is nearly the same :D
You can use the default filter. (Read more)
{{ special_knowledge.knowledgecost|safe|default:"Doesnt exist" }}

How can I have my template display a list on two different div tags without having redundancies

I have a list from my Model but I want my template to display the list element in groups of 4 or half the total length of the list Example: let say i have 10 elements in my list i want 5 on the right size and 5 on the left side. Please see screenshot below.
This is how i want my page to look like:
But this is what i get:
This is my HTML file.
<div class="section-title">
<h2>Skills</h2>
<p>hsjkhvdkdjhvjkdfnv kjdf, dfhvkhdnfvkjldf,xhvnkldsv.mckldfnv ,dfhxncjcshfxdjvhcnjsdnckndjvbc d,sxbc kjdjsxcbjdksbvc kjs,bhzscs,zhcnlksjhlnzcklsnzjcjsdzcjb ds
cxdbjvcsdbzcjks,gdcbkjds,zbcn jkcdxbv,m dfxvchj bdxnvbjhdujxdnkck jdfvknc dfkjhvxjdknfxzjxvkc.
</p>
</div>
{% for skill in skills_list%}
<div class="row skills-content">
<div class="col-lg-6" data-aos="fade-up">
<div class="progress">
<span class="skill">{{skill.skill_name}} <i class="val">{{skill.skill_value}}</i></span>
<div class="progress-bar-wrap">
<div class="progress-bar" role="progressbar" aria-valuenow={{skill.skill_value}} aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
views.py:
#### TEST
class TestView(generic.ListView):
model = Skills
template_name = 'portfolio_app/test.html'
########################URL.py
from django.urls import path
from portfolio_app.models import *
from . import views
urlpatterns = [
path('',views.fact,name='index'),
#path('index/',views.SkillView.as_view,name='index'),
path('about/',views.about_me,name='about'),
path('service/',views.ServiceView.as_view(),name='service'),
path('resume/',views.ResumeView.as_view(),name='resume'),
path('contact/',views.ContactView.as_view(),name='contact'),
path('test/',views.TestView.as_view(),name='test'),
]
You can try to move <div class="row skills-content"> outside the for loop like this:
<div class="section-title">
<h2>Skills</h2>
<p>hsjkhvdkdjhvjkdfnv kjdf, dfhvkhdnfvkjldf,xhvnkldsv.mckldfnv ,dfhxncjcshfxdjvhcnjsdnckndjvbc
d,sxbc kjdjsxcbjdksbvc kjs,bhzscs,zhcnlksjhlnzcklsnzjcjsdzcjb ds
cxdbjvcsdbzcjks,gdcbkjds,zbcn jkcdxbv,m dfxvchj bdxnvbjhdujxdnkck jdfvknc
dfkjhvxjdknfxzjxvkc.
</p>
</div>
<div class="row skills-content">
{% for skill in skills_list%}
<div class="col-lg-6" data-aos="fade-up">
<div class="progress">
<span class="skill">{{skill.skill_name}} <i class="val">{{skill.skill_value}}</i></span>
<div class="progress-bar-wrap">
<div class="progress-bar" role="progressbar" aria-valuenow={{skill.skill_value}}
aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
</div>
{% endfor %}
</div>
And you should remove redundant last </div> to make it work correctly.
Use slice like this:
<div class="row skills-content">
<div class="col-lg-6" data-aos="fade-up">
{% for skill in skills_list|slice:":5" %}
<div class="progress">
<span class="skill">{{skill.skill_name}} <i class="val">{{skill.skill_value}}</i></span>
<div class="progress-bar-wrap">
<div class="progress-bar" role="progressbar" aria-valuenow={{skill.skill_value}} aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
{% endfor %}
</div>
<div class="col-lg-6" data-aos="fade-up">
{% for skill in skills_list|slice:"5:" %}
<div class="progress">
<span class="skill">{{skill.skill_name}} <i class="val">{{skill.skill_value}}</i></span>
<div class="progress-bar-wrap">
<div class="progress-bar" role="progressbar" aria-valuenow={{skill.skill_value}} aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
{% endfor %}
</div>
</div>
To get rid of redundant div's create a separate template for skills and include that in you current template using include template tag like this:
skills.html:
<div class="progress">
<span class="skill">{{skill.skill_name}} <i class="val">{{skill.skill_value}}</i></span>
<div class="progress-bar-wrap">
<div class="progress-bar" role="progressbar" aria-valuenow={{skill.skill_value}} aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
your current temple:
<div class="row skills-content">
<div class="col-lg-6" data-aos="fade-up">
{% for skill in skills_list|slice:":5" %}
{% include 'skills.html' with skill=skill %}
{% endfor %}
</div>
</div>
similarly for second loop.

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