flask template jinja not looping as expected - python

I have a flask app with a template inside which I have a loop using jinja syntax. The problem is I don't know why the row[5] is not changing while others are working fine. The <p>{{ row[5] }}</p> is not looping probably in that div nested inside the td tag. The data sent to the page should be looped for 4 times. {{ row[5] }} this keeps giving me the value of the first loop. The code is as following:
{% for row in data %}
<tr>
<td>{{ row[2] }}</td>
<td>{{ row[1] }}</td>
<td>{{ row[3] }}</td>
<td>
<button type="button" class="btn btn-info btn-sm" data-toggle="modal" data-target="#myModal">Backup</button>
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<p>{{ row[5] }}</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</td>
<td>Backup</td>
</tr>
{% endfor %}
Even though the data does not matter here. Since someone asked , I will put it here. Data is something like:
data=((1,2,3,4,5,6,7,8),(1,2,3,4,5,6,7,8))
This is the way I render the template:
#app.route('/home')
def home(methods=['GET']):
cursor = conn.cursor()
cursor.execute("SELECT * from hosts_custom;")
data = cursor.fetchall()
print data
return render_template('index.html',data=data)
It turns out it's the id and the target stay the same all the time. So when I click on the button it keeps jupping to the myModal target. Thanks everyone for your help!
Solution
The solution I use is pretty simple.
<button type="button" class="btn btn-info btn-sm" data-toggle="modal" data-target="#myModal{{ loop.index }}">Backup</button>
<div id="myModal{{ loop.index }}" class="modal fade" role="dialog">

Related

Jinja2-Flask bootstrap modal inside a for loop doesn't work

I am trying to list a bunch of information on a table and I want user to be able to click an icon and see the description of the content. My project is TODO list. I am showing the user {{ task.title }} within a for loop and I have an icon/button next to it to open the modal.
When I put my modal button inside my for loop and modal content outside the for loop, I am not able to catch the current data, example:
{{ task.description }} I can't catch this information from my database because I am outside the loop and I get jinja2 error because of this saying task is undefined.
If I put my modal content inside the for loop, then my modal is not working properly, modal screen kinda gets foggy and faded. I am adding an image of this error here.
IMG when I put my modal content inside the for loop, I get this screen
Anyone solved this issue before? It probably has an easy solution but I've been trying for days now I am kinda tilted...
My code:
<tbody class="align-middle">
{% for task in active_tasks: %}
<tr>
<td>{{task.deadline}}</td>
<td>
<a type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modal">
Title
</a>
<div class="modal fade" id="modal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
{{ task.description }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</td>
<td>
{% if task.priority == "High Priority": %}
<span class="badge bg-danger">{{ task.priority }}</span>
{% elif task.priority == "Medium Priority": %}
<span class="badge bg-warning">{{ task.priority }}</span>
{% else: %}
<span class="badge bg-success">{{ task.priority }}</span>
{% endif %}
</td>
<td>
<a href="{{ url_for('complete_task', id=task.id) }}" data-mdb-toggle="tooltip" title="Complete">
<i class="bi bi-check-lg check-icon"></i></a>
<a href="{{ url_for('delete_task', id=task.id, status='active') }}" data-mdb-toggle="tooltip" title="Remove">
<i class="bi bi-trash trash-icon"></i></a>
</td>
</tr>
{% endfor %}
</tbody>
Don't add your modal into your for loop. You can access the data using vanilla javascript. Search this in Google or YouTube
access table data with button using vanilla javascript

All Delete buttons are attached to the first row

I have the following code where it display some data in rows, there's "Delete" button with each button.
in my case the "Delete" button will always delete the first row in the list, even if I try to delete something in the middle or end the last row from the list, the first row gets deleted.
not sure why all buttons are associated with the first row while they're in FOR loop.
Update#1: I did some tests and I can see that each button is aware of the correct data for it's own row, but after I click the button it hits data-target="#deleteLocation" and this new section "#deleteLocation" is always aware of the first row only.
routes.py
#org_settings.route("/locations", methods=["GET"])
def locations():
form = LocationForm()
page = request.args.get("page", 1, type=int)
locations = (
Location.query.filter_by(user_id=current_user.id)
.order_by(Location.name.asc())
.paginate(page=page, per_page=5)
)
return render_template(
"settings/locations.html",
title="Locations",
locations_tab="active",
locations=locations,
form=form,
)
#org_settings.route("/locations/<int:location_id>/delete", methods=["GET", "POST"])
#login_required
def delete_location(location_id):
location = Location.query.get_or_404(location_id)
if location.organization != current_user:
abort(403)
db.session.delete(location)
db.session.commit()
flash("Your location has been deleted!", "info")
return redirect(url_for("org_settings.locations"))
locations.html
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">Location Name</th>
<th scope="col">Latitude</th>
<th scope="col">Longitude</th>
<th scope="col">Address</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{% for location in locations.items %}
<tr>
<td>{{ location.name }}</td>
<td>{{ location.latitude }}</td>
<td>{{ location.longitude }}</td>
<td>{{ location.address }}</td>
<td>
<button type="button" class="btn btn-danger btn-sm" data-toggle="modal" data-target="#deleteLocation">
<i class="bi bi-trash-fill" style="font-size:18px; color: rgb(255, 255, 255);"></i>
</button>
<!-- Bootstrap Modal -->
<div class="modal fade" id="deleteLocation" data-backdrop="static" data-keyboard="false" tabindex="-1"
aria-labelledby="deleteLocationLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="deleteLocationLabel">Delete Location</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Are you sure you would like to delete this location?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<form action="{{ url_for('org_settings.delete_location', location_id=location.id) }}"
method="POST">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</div>
</div>
</div>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
I solved it by adding the ID of the row {{ location.id }} to the id of html section
data-target="#deleteLocation-{{ location.id }}"
as below
<button type="button" class="btn btn-danger btn-sm" data-toggle="modal"
data-target="#deleteLocation-{{ location.id }}">
<i class="bi bi-trash-fill" style="font-size:18px; color: rgb(255, 255, 255);"></i>
</button>```
<div class="modal fade" id="deleteLocation-{{ location.id }}" data-backdrop=" static" data-keyboard="false"
tabindex="-1" aria-labelledby="deleteLocationLabel" aria-hidden="true">

How to pass data from table of record to Modal

i know this question has been asked a lot, but all solution are not suitable for me.I essentially have a table inside a view that is displayed using a foreach loop in HTML and sqlalchemy ,this spits out the records one by one and appends some 'Action' buttons in the last column ( delete and edit),I just pass the ID in from each record in the foreach loop, then job done.
I'm having a lot of issues with my modal though, it only ever displays the data from the first record when I echo the data in the 'value' field of each input,I'm really stumped on how to make this functionality work (javascriptis not my strongest language), it's possible work without using Ajax and php?
i am using flask, python and sqlalchemy.
I think the issue is that the modal is only created once when the foreach loop starts running, hence why it only ever has the first record data inside the modal, any help to get around this so I can edit each individual record inside the table would be great! Thanks for the help.
my html code
{% extends "layout.html" %}
{% block title %}
Admin
{% endblock %}
{% block body %}
<h1> Admin</h1>
<div class="form-group">
<table border=1>
<tr>
<th>usa_order_id</th>
<th>user_id</th>
<th>cpu</th>
</tr>
{% for usa_order in usa_orders %}
<tr>
<th><input class="form-control" name ="usa_order_id" value={{usa_order.usa_order_id}}></th>
<th><input class="form-control" name ="user_id" value={{usa_order.user_id}}></th>
<th><input class="form-control" name ="cpu" value={{usa_order.cpu}}></th>
<th>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal">
Open modal
</button>
<!-- The Modal -->
<div class="modal" id="myModal">
<div class="modal-dialog">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" >×</button>
</div>
<!-- Modal body -->
<div class="modal-body">
<div class="form-group">
<input class="form-control" name ="usa_order_id" value=usa_order_id>
<input class="form-control" name ="user_id" value=user_id>
<input class="form-control" name ="cpu" value=cpu>
</div>
</div>
<!-- Modal footer -->
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</th>
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
my flask python code
from flask import Flask, render_template, request
from flask_sqlalchemy import SQLAlchemy
from model import *
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI']='mysql://root:xxx#localhost:3306/xxx'
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN']=True
db = SQLAlchemy(app)
#app.route("/admin")
def index():
usa_order = usa_order.query.all()
return render_template("admin.html",usa_order = usa_order)
if __name__ == '__main__':
app.run(debug=True,host="0.0.0.0")
my model.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class usa_order(db.Model):
__tablename__ = "usa_order"
usa_order_id = db.Column(db.Integer,primary_key = True)
cpu = db.Column(db.String, nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey("user.user_id"), nullable=False)
I think you'll need to give each Modal a unique ID, so it wouldn't be always superseded by the Modal generated first. Try the following HTML instead:
{% extends "layout.html" %}
{% block title %}
Admin
{% endblock %}
{% block body %}
<h1> Admin</h1>
<div class="form-group">
<table border=1>
<tr>
<th>usa_order_id</th>
<th>user_id</th>
<th>cpu</th>
</tr>
{% for usa_order in usa_orders %}
<tr>
<th><input class="form-control" name ="usa_order_id" value={{usa_order.usa_order_id}}></th>
<th><input class="form-control" name ="user_id" value={{usa_order.user_id}}></th>
<th><input class="form-control" name ="cpu" value={{usa_order.cpu}}></th>
<th>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal{{usa_order.id}}">
Open modal
</button>
<!-- The Modal -->
<div class="modal" id="myModal{{usa_order.id}}">
<div class="modal-dialog">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" >×</button>
</div>
<!-- Modal body -->
<div class="modal-body">
<div class="form-group">
<input class="form-control" name ="usa_order_id" value=usa_order_id>
<input class="form-control" name ="user_id" value=user_id>
<input class="form-control" name ="cpu" value=cpu>
</div>
</div>
<!-- Modal footer -->
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</th>
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
NOTE: All i did there is to add the record ID to the Modal ID.

How do i make a functioning Delete confirmation popup in Django using Bootstrap4 Modal

My views.py file looks like this.
def deleteOrder(request, pk):
order = Order.objects.get(id=pk)
if request.method=="POST":
order.delete()
return redirect('/')
context = {"item":order}
return render(request, 'accounts/delete.html', context)
My delete.html file is this. If there is a way to get rid of it or use part of it's code in the delete popup then kindly assist.
{% block content %}
<br>
<div class="row">
<div class="col-md-6">
<div class="card card-body">
<p>Are you sure you want to delete "{{item}}"?</p>
<form action="{% url 'delete_order' item.id %}" method="POST">
{% csrf_token %}
<a class="btn btn-warning" href="{% url 'home' %}">Cancel</a>
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</div>
</div>
</div>
{% endblock %}
My urls.py file looks like this.
urlpatterns = [
path('delete_order/<str:pk>', views.deleteOrder, name="delete_order"),
]
Bootstrap Delete Popup i need help applying.
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
Launch demo modal
</button>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
My Home page made of a table which contains a Delete column for deleting each row.
<table class="table table-sm">
<tr>
<th>Product</th>
<th>Date Ordered</th>
<th>Status</th>
<th>Update</th>
<th>Delete</th>
</tr>
{% for order in orders %}
<tr>
<td>{{ order.product }}</td>
<td>{{ order.date_created }}</td>
<td>{{ order.status }}</td>
<td><a class="btn btn-sm btn-info" href="{% url 'update_order' order.id %}">Update</a></td>
**<td><a class="btn btn-sm btn-danger" href="{% url 'delete_order' order.id %}">Delete</a></td>**
</tr>
{% endfor %}
</table>
The Line that i have added ** asterisks(intentionally) is the one i want to modify so that when i click on Delete button, a Bootstrap delete popup modal gets triggered.
Try this.
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<a class="btn btn-sm btn-danger" href="{% url 'delete_order' order.id %}">Delete</a>
</div>
</div>
</div>
</div>
<table class="table table-sm">
<tr>
<th>Product</th>
<th>Date Ordered</th>
<th>Status</th>
<th>Update</th>
<th>Delete</th>
</tr>
{% for order in orders %}
<tr>
<td>{{ order.product }}</td>
<td>{{ order.date_created }}</td>
<td>{{ order.status }}</td>
<td><a class="btn btn-sm btn-info" href="{% url 'update_order' order.id %}">Update</a></td>
<td><a class="btn btn-sm btn-danger" href="#" data-toggle="modal" data-target="#exampleModal">Delete</a></td>
</tr>
{% endfor %}
</table>
--- UPDATE ---
url.py, most common use is urls.py
Your pk should to be int not str
urlpatterns = [
path('delete_order/<int:pk>', views.deleteOrder, name="delete_order"),
]

How to load content dynamically from database into Bootstrap modal using Django

I am working on a testing app that lists out users from the database in a HTML table, what I want to achieve is this, when you click on any icon for a particular record or row the full detail of that record is displayed in a Bootstrap Modal. My problem is how do I implement my views, urls, and also my Templates? Do I need Javascript help here? Cause in PHP this is done easily without JavaScript. Plesae I will prefer code samples as a correction to my issue thanks.
Here is my view
def users(request):
get_users = User.objects.all()
return render(request, 'classwork_app/users.html', {'users':get_users})
My urls
from classwork_app import views
app_name = 'classwork_app'
urlpatterns = [
path('', views.users, name='users'),
]
Templates
<table class="table table-bordered">
<tr>
<th>S/N</th>
<th>Username</th>
<th>Firstname</th>
<th>Lastname</th>
<th colspan="2">Action</th>
</tr>
{% if users %}
{% for u in users %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ u.username }}</td>
<td>{{ u.first_name }}</td>
<td>{{ u.last_name }}</td>
<td style="font-size: 12px"><a data-toggle="modal" href="#MyModal{{ u.id }}"><i class="fa fa-eye"></i></a></td>
</tr>
{% endfor %}
{% endif %}
</table>
<div id="#MyModal{{ u.id }}" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">{{ u.first_name }} {{ u.last_name }}</h4>
</div>
<div class="modal-body">
<p>
Username: {{ u.username }}
Firstname: {{ u.first_name }}
Lastname: {{ u.last_name }}
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
you can try putting your modal html code inside the for user iterator. This way it will load a modal with user content for every user in your list (not very recommended if you have a lot of data, can cause performance issues)

Categories