Flask render_template taking 5+ seconds to run - python

I'm trying to display a page with some data, passing a dictionary through to the jinja template. This takes a ridiculously long time to load, easily 5-10 seconds for a very small dataset. This is what my Python looks like
#app.route("/request")
def request_page():
category_dict = CONFIG.get_categories()
return render_template('request.html', category_dict=category_dict)
And this is what my HTML looks like
{% extends "layout.html" %}
{% block title %}Categories{% endblock %}
{% block content %}
<h1 class="display-4">Category List</h1>
<form method='post' action='/result' onsubmit="return checkForm(this)">
<div class="form-group">
{% for category, list in category_dict.items() %}
<div class="card">
<div class="card-header">
<a class="text-dark" data-toggle="collapse" href="#{{loop.index}}">
{{category}}
</a>
</div>
<div id="{{loop.index}}" class="collapse">
<div class="card-body text-small">
<ul class="list-group list-group-flush">
{% for project in list %}
<li class="list-group-item">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="checkbox" value="{{project}}" id="{{project}}">
<label class="form-check-label" for="{{project}}">
{{project}}
</label>
</div>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endfor %}
<br>
<h5>Reason for group access</h5>
<textarea rows="4" cols="60" name="reasons">
</textarea>
<br>
<button class='btn btn-primary' name='Submit'>Submit</button>
</form>
{% endblock %}
So as an overview, its a nested for loop where the outer loop iterates through the key value pairs of the dictionary and the inner loop iterates through the values, which are lists of strings. The dictionary that I'm passing through isn't very big, ~5 keys and maybe ~5 items in each list. Doing some tests also revealed that the slowdown is definitely with this chunk of code in the HTML, not in the layout.html or anything.

Related

Flask apply filter with multiple checkboxes

Hey good people of stackoverflow,
My application randomly selects a recipe from MongoDB (using pymongo) and displays it to the user.
My intention is to be able to apply filters (vegetarian, fish, beef and so on) to the next "random" selection after hitting Something else button.
I think I can achieve it by using request.form.getlist and creating the form in the pick_meal.html but it feels a bit overkill.
So far I am unable to figure it out.
Any help would be greatly appreciated.
The html and python function looks like this:
{% extends 'base.html' %}
{% block content %}
<div class="container">
<h3>{% block title %} You should cook: {% endblock %}</h3>
<div class="row">
<div class="col-md-5 align-self-center text-center">
<span>{{ dish.dish_name }}</span>
</br>
</br>
<a class="btn btn-outline-success" href="{{ dish['dish_source'] }}" role="button">Go to web</a>
</div>
<div class="col-md-4">
<img src="{{ dish.dish_image }}" width="250px">
</div>
</div>
</br>
<div class="row">
<div class="col-md-5">
<button class="btn btn-primary">Something else</button>
<button class="btn btn-primary">Configrm choice</button>
<button class="btn btn-primary">Already cooked</button>
</div>
<div class="col-md-5">
<div class="form-check">
<input class="form-check-input" type="checkbox" value="vegetarian" id="flexCheckDefault" name="property_checkbox">
<label class="form-check-label" for="flexCheckDefault">Vegetarian</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="grill" id="flexCheckDefault" name="property_checkbox">
<label class="form-check-label" for="flexCheckDefault">Grill</label>
</div>
</div>
</div>
</div>
{% endblock %}
#app.route('/pick_meal/<string:dish_type>')
def pick_meal(dish_type):
# pick random meal based on category
dish = list(coll.aggregate([
{'$match':{
'cooked': False,
'dish_type': dish_type}},
{ '$sample':{
'size': 1 } }]))[0]
return render_template('pick_meal.html', dish=dish, dish_type=dish_type)

collapsing accordion content in django for loop

I am trying to implement for loop in my accordion. Everything seems to be fine except the fact that when I click on 3rd or 4th button then other bodies stay expanded. It should work exactly the same as in the first example in Bootstrap documentation so if you click on Accordion Item #2 then Accordion Item #1 and Accordion Item #3 collapse.
I am sure that the issue is with my {% if forloop.first %} but I am not sure how can I dynamically change that so it will collapse all accordion contents except active one.
My code:
{% for category in top_categories %}
<div class="accordion" id="accordionExample">
<div class="accordion-item">
<h2 class="accordion-header" id="heading{{category.id}}">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#collapse{{category.id}}" aria-expanded="false" aria-controls="collapse{{category.id}}">
{{category.title}}
</button>
</h2>
<div id="collapse{{category.id}}" class="accordion-collapse {% if forloop.first %} show {% else %} collapse {% endif %}" aria-labelledby="heading{{category.id}}"
data-bs-parent="#accordionExample">
<div class="accordion-body">
{% for qa in category.qa.all|slice:"0:3" %}
Q: {{qa}}<hr>
{% endfor %}
</div>
</div>
</div>
</div>
{% endfor %}
I think that the main problem is that you are including <div class"accordion" id="accordionExample"> inside the loop. A secondary one is that the "collapse" class is also necessary for the first iteration. Try this:
<div class="accordion" id="accordionExample">
{% for category in top_categories %}
<div class="accordion-item">
<h2 class="accordion-header" id="heading{{category.id}}">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapse{{category.id}}" aria-expanded="true" aria-controls="collapse{{category.id}}">
{{category.title}}
</button>
</h2>
<div id="collapse{{category.id}}" class="accordion-collapse collapse {% if forloop.first %}show{% endif %}" aria-labelledby="heading{{category.id}}" data-bs-parent="#accordionExample">
<div class="accordion-body">
{% for qa in category.qa.all|slice:"0:3" %}
Q: {{qa}}<hr>
{% endfor %}
</div>
</div>
</div>
{% endfor %}
</div>

Python Jinja2 loop index to make id unique

I'm using jinja2 template with Flask and MongoDB and I need to display users' cars in a template.
I was able to render cars in the profile template with car information and buttons to edit or delete a car. The problem is that if a user has multiple cars, only the first DELETE CAR button actually works (where I have an include modals to confirm) but nothing happens when click on the second or third delete button. Apparently I duplicated the id that needs to be unique. But I cannot achieve the results.
Here is my template: profile.html
{% extends 'layout/base.html' %}
{% block content %}
{% include 'components/navigation/navigation.html' %}
<div class="container">
<div class="row g-3 justify-content-center">
<div class="col-6 mt-5">
<div class="card">
<div class="card-body">
<h3 class="text-center profileHeader">
{{ username }}'s profile
</h3>
</div>
</div>
</div>
</div>
<div class="row row justify-content-center mt-4">
{% for car in cars %}
{% if session.user|lower == car.created_by|lower %}
<div class="card mb-3" style="max-width: 840px;">
<div class="row g-0">
<div class="col-md-4">
<img src="{{ car.car_image }}" class="imgCard" alt="ferrari image">
</div>
<div class="col-md-8">
<div class="card-body">
<ul class="list-group list-group-flush">
<li class="list-group-item"><strong>Year</strong>: {{ car.car_year }} </li>
<li class="list-group-item"><strong>Name</strong>: {{ car.car_name }}</li>
<li class="list-group-item"><strong>Designer</strong>: {{ car.car_design }}</li>
</ul>
<ul class="list-group list-group-flush">
<li class="list-group-item"><strong>Engine</strong>: {{ car.spec_engine }}</li>
<li class="list-group-item"><strong>Power</strong>: {{ car.car_power }}</li>
<li class="list-group-item"><strong>Trasmission</strong>: {{ car.trasmission }}</li>
<li class="list-group-item"><strong>Races</strong>: {{ car.races }}</li>
<li class="list-group-item"><strong>Wins</strong>: {{ car.wins }}</li>
<li class="list-group-item"><strong>Podiums</strong>: {{ car.podiums }}</li>
<li class="list-group-item"><strong>Poles</strong>: {{ car.poles }}</li>
<li class="list-group-item"><strong>Fast Laps</strong>: {{ car.fast_laps }}</li>
<li class="list-group-item"><strong>Constructor Championship</strong>: {{
car.constructor_champ
}}</li>
<li class="list-group-item"><strong>Driver Championship</strong>: {{ car.drivers_champ }}
</li>
<li class="list-group-item"><strong>Description</strong>: {{ car.description }}</li>
<p><em>by: {{ car.created_by }}</em></p>
</ul>
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a id="myBtn" class="btn btn-danger"><i class=" fas fa-trash-alt"></i> Delete</a>
<a href="{{ url_for('editcar', car_id=car._id) }}" class="btn btn-danger" id="edit-btn"><i
class="far fa-edit"></i> Edit</a>
{% with car_id=car._id %}
{% include 'components/modals/confirm.html' %}
{% endwith %}
</div>
</div>
</div>
</div>
</div>
{% endif %}
{% endfor %}
</div>
enter code here
</div>
{% endblock %}
Just make unique the tag id of delete button, so the trigger will be unique in every button. How to make unique ? just add the car._id on tag id
<a id="myBtn-{{car._id}}" class="btn btn-danger"><i class=" fas fa-trash-alt"></i> Delete</a>
As #Darn pointed out, your ids need to be unique. But that is not the cause of your issue here.
I assume you have some Javascript code that gets triggered when user clicks on the delete link. The issue is probably from how that code is being triggered. The code needs to be written in such a way that it is bound to dynamically generated elements (you're generating the delete links on the fly i.e. afte the code for the delete was already bound; that delete code needs to also apply to each element when it is created).
You should bind the delete action to a class e.g.
$(".fa-trash-alt").on("click", function(){
$(this).parent() ...... // this is the link to the instance of the link that was clicked
});

Djago template card alignement [Django 2.2]

I Need your help please.
My envirenement is:
python 3.6.6
django 2.2
I want to generate some code like this using django template.
<div class="card-deck">
<div class="card">
actu1
</div>
<div class="card">
actu2
</div>
<div class="card">
actu3
</div>
<div class="card">
actu4
</div>
</div>
<!--insert inside a new div (with class card-deck) the 5th actu and next one-->
<div class="card-deck">
<div class="card">
actu5
</div>
<div class="card">
actu6
</div>
<div class="card">
actu7
</div>
<div class="card">
actu8
</div>
</div>
<!--insert inside a new div (with class card-deck) the 9th actu and next one-->
what I manage to do with django templates is as follows:
{% extends 'actu/base_actu.html'%}
{% load static %}
{%block actumain%}
<div class="card-deck">
{%for actu in actu%}
<div class="card">
{ {actu.content }}
</div>
{%endfor%}
</div>
{%endblock%}
which just gives the code as follows:
<div class="card-deck">
<div class="card">
actu1
</div>
<div class="card">
actu2
</div>
<div class="card">
actu3
</div>
<div class="card">
actu4
</div>
<div class="card">
actu5
</div>
<div class="card">
actu7
</div>
<div class="card">
actu8
</div>
<div class="card">
actu9
</div>
<div class="card">
actu10
</div>
<div class="card">
actu11
</div>
<div class="card">
actu...
</div>
</div>
Please, could you give me your idea to be able to generate such a code.
Thank you very much.
Use the forloop.counter0 and the divisibleby tempate tag like this:
{% for actu in actu %}
{% if forloop.counter0|divisibleby:"4" and not forloop.first %}
</div>
{% endif %}
{% if forloop.counter0|divisibleby:"4" %}
<div class="card-deck">
{% endif %}
<div class="card">
{{ actu.content }}
</div>
{% if forloop.last %}
</div>
{% endif %}
{% endfor %}
Here we first check if the loop counter is divisible by 4 and not the first iteration if yes we render the closing div tag.
Next we if the loop counter is divisible by 4 and if so we render the opening div tag.
After this we render the individual cards.
Next we check if this is the last iteration if so we render the closing div tag.
{% for item in actu %}
{% if forloop.counter0|divisableby:4 %}
<div class="card-deck">
{% endif %}
<div class="card">
{{ item.content }}
</div>
{% if forloop.counter0|divisableby:4 or forloop.last %}
</div>
{% endif %}
{% endfor %}

Django forloop and all selectable radio buttons

Here is a seemingly simple task, creating a form using a set of records so the user can choose which record to go for, all using a radio button.
<form action="" method="GET">{% csrf_token %}
{% for record in select_records %}
<div class="form-check indent-3">
<label class="form-check-label" for="radio{{forloop.counter}}">
<input type="radio" class="form-check-input" id="radio{{forloop.counter}}" name="{{record.get_model_name}}{{record.id}}" value="{{record.record_name}}">
{% if request.user.userprofile.head_shot_thumb %}
<img src="{{ request.user.userprofile.head_shot_thumb }}" alt="Proforma creator">
{% else %}
<div class="h2-li ">
<i class="fas fa-user"></i>
</div>
{% endif %}
{{ record.record_name }} - {{ record.date_created }}
</label>
</div>
{% endfor %}
The problem is that the form creates a list of radio buttons which are all selectable, just like how all the checkboxes are selectable.
I have searched and compared my code to simple radio forms such as the one at W3schools, but I cannot figure it out. Any help is appreciated.
I did small changes in your code. Check it below.
<form action="" method="GET">
{% csrf_token %}
{% for record in select_records %}
<div class="form-check indent-3">
<label class="form-check-label" for="radio{{forloop.counter}}">
<input type="radio" class="form-check-input" id="radio{{forloop.counter}}" name="record-option" value="{{record.record_name}}">
{% if request.user.userprofile.head_shot_thumb %}
<img src="{{ request.user.userprofile.head_shot_thumb }}" alt="Proforma creator">
{% else %}
<div class="h2-li ">
<i class="fas fa-user"></i>
</div>
{% endif %}
{{ record.record_name }} - {{ record.date_created }}
</label>
</div>
{% endfor %}
</form>
I hope this will help you. :)

Categories