django how to implement a dynamic (bootstrap) modal - django

I'm trying to change the interaction of a page so that additional info about a product appears in a modal rather than an element that is shown/hidden when a button is clicked.
The bit I'm not sure about is making the modal adapt it's contents to each product. (I'm not sure if django must prepare 3 different modals first of all at the backend - if this is possible or whether there is a simpler way?)
Previously I had the template:
<div class="item price-2 col-md-4 col-12 text-center best-buy">
<div class="item-inner">
<div class="heading">
<h3 class="title"><b>Cheapest</b></h3>
</div>
{% include 'components/quote_summary_item.html' with quote=first_quote %}
</div><!--//item-inner-->
</div><!--//item-->
{% include 'components/quote_detail.html' with quote=first_quote %}
Where quote_summary_item.html is:
<div>
<div class="quotes-summary"><img src="{{ quote.ImageUrl }}" alt=""></div>
<p></p>
<p >.........
</p>
<a class="btn btn-quote-primary" href="{% url 'users:profile %}">Select</a></div>
<div class="content">
<p><b>Your Quote Details</b></p>
<p>{{ quote.Name }}<br/>
{{ quote.Type }} <br/>
.....
</p>
<button class="btn btn-cta-secondary" data-id="{{ quote.priceId }}">Info</button>
</div><!--//content-->
and quote_detail is:
<div class="quote" id="quote{{ quote.priceId }}" style="display:none">
<div >
<p><b>About this quote:</b></p>
{{ quote.synopsisText|safe }}
</div>
<div class="row">
<div class="col">
<table class="table">
<thead class="til-table-head">
<tr>
<th>Information</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td>{{ quote.Something }}</td>
</tr>
<tr>
<td>Name</td>
<td>{{ quote.Name }}</td>
</tr>
<tr>
<td></td>
<td>{{ quote.payType }}</td>
</tr>
.......
</tbody>
</table>
</div>
</div>
</div>
And the .js used was:
<script type="text/javascript">
$(document).ready(function () {
$('.btn-cta-secondary').click(function (e) {
var id = $(e.currentTarget).data('id')
$('.quote').hide()
$('#quote' + id).show()
})
})
</script>
I've set up a modal template wrapper around quotes_detail.html however I'm not sure how to change the .js needed to pass in the relevant quote data to something like:
{% include 'components/quotes_modal.html' with quote=my_quote %}
and pass in the relevant quote based on the button id clicked.

There are two decent ways to do this. Implement multiple modals if there aren't too many of them or use ajax to retrieve the contents if there are lots of them.
There is no need to have a .js file as all the required js is built into bootstrap.
Control each modal with eg a button:
<button type="button" class="btn btn-cta-secondary" data-toggle="modal" data-target="#{{ quote.priceId }}" data-id="{{ quote.priceId }}">More Info</button>
Then include the modal template in the relevant page:
{% include 'components/quote_detail.html' with quote=second_quote %}
{% include 'components/quote_detail.html' with quote=first_quote %}
with components/quote_details.html
<div class="modal fade" id="{{ quote.priceId }}" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
.....
with the rest as per bootstrap docs.
To do this via ajax have a look at https://www.abidibo.net/blog/2015/11/18/modal-django-forms-bootstrap-4/

Related

Django delete record using modal

I'm new in Django and i like to implement a Modal to delete records. The problem is a funny error in the modal form because is expecting a parameter. The modal link has this
but I don't know how add the right parameter.
This is my List in html
<table id="tablaAlmacenes" class="table table-bordered table-striped">
<thead>
<tr>
<th>Almacén</th>
<th>Detalles</th>
<th></th>
</tr>
</thead>
<tbody>
{% for almacen in object_list %}
<tr>
<td>{{ almacen.almacen }}</td>
<td>{{ almacen.descripcion }}</td>
<td>
<div>
Detalles
<a a href="" class="btn btn-link text-primary">Editar</a>
<a class="btn btn-link deleteAlmacen" data-id="{{ almacen.id}}"><span class="fas fa-trash text-danger"></a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<th>Almacén</th>
<th>Detalles</th>
<th></th>
</tr>
</tfoot>
</table>
this is my url.py
urlpatterns = [
path('',include('polls.urls'),name='home'),
path('admin/', admin.site.urls),
# path('contact/',views.contact, name='contacto')
path('almacenes/', AlmacenesListView.as_view(), name='almacenes'),
path('almacenes/nuevo', AlmacenesCreateView.as_view(), name='crear_almacen'),
path('almacenes/<int:id>/remove/', AlmacenesDeleteView.as_view(), name='eliminar_almacen')
]
This is my views.py
class AlmacenesListView(ListView):
model = Almacen
template_name = 'pages/index.html'
success_message = "Bien!!!!"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = "Lista de Almacenes"
print(reverse_lazy('almacenes'))
return context
class AlmacenesCreateView(SuccessMessageMixin, CreateView):
model = Almacen
form_class = AlmacenesForm
success_url = reverse_lazy('almacenes')
success_message = "Bien!!!!"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
return context
class AlmacenesDeleteView(DeleteView):
model = Almacen
success_url = reverse_lazy('almacenes')
and my modal code
<div class="modal fade" aria-modal="false" id="deleteAlmacenModal">
<div class="modal-dialog modal-dialog-centered modal-sm">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Confirmación</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Cerrar">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>¿Desea eliminar el Almacen?</p>
</div>
<div class="modal-footer justify-content-between">
<button type="button" class="btn btn-default" data-dismiss="modal">Cerrar</button>
<form action="{% url 'eliminar_almacen' (some parameter here but error) %}" method="POST">
{% csrf_token %}
<input type="hidden" name="id" id="almacen_id"/>
<button type="submit" class="btn btn-danger">Eliminar</button>
</form>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
scrpt for modal
$(document).on('click','.deleteAlmacen',function(){
var id_almacen=$(this).attr('data-id');
$('#almacen_id').val(id_almacen);
$('#deleteAlmacenModal').modal('show');
});
So, if you are using bootstrap you don't need to trigger the modal with jquery but let bootstrap do the magic.
Your code should be something like that:
html:
<table id="tablaAlmacenes" class="table table-bordered table-striped">
<thead>
<tr>
<th>Almacén</th>
<th>Detalles</th>
<th></th>
</tr>
</thead>
<tbody>
{% for almacen in object_list %}
<tr>
<td>{{ almacen.almacen }}</td>
<td>{{ almacen.descripcion }}</td>
<td>
<div>
Detalles
<a a href="" class="btn btn-link text-primary">Editar</a>
<a class="btn btn-link" data-toggle="modal" data-target="#deleteAlmacenModal{{almacen.id}}""><span class="fas fa-trash text-danger"></a> <!-- data-toggle and data-target work in bootstrap4, in 5 is data-bs-target and data-bs-toggle -->
{% include 'yourtemplatefolder/modals/delete_almacen_modal.html' %} <!-- as best practice create another folder called modals and put there you modal.html files, as in this case and include them in your code -->
</div>
</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<th>Almacén</th>
<th>Detalles</th>
<th></th>
</tr>
</tfoot>
</table>
Now, being the modal called inside the for loop, you can fix your modal like this:
delete_almacen_modal.html
<div class="modal fade" aria-modal="false" id="deleteAlmacenModal{{almacen.id}}">
<div class="modal-dialog modal-dialog-centered modal-sm">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Confirmación</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Cerrar">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>¿Desea eliminar el Almacen?</p>
</div>
<div class="modal-footer justify-content-between">
<button type="button" class="btn btn-default" data-dismiss="modal">Cerrar</button>
<form action="{% url 'eliminar_almacen' pk=almacen.id %}" method="POST">
{% csrf_token %}
<input type="hidden" name="id" id="almacen_id"/>
<button type="submit" class="btn btn-danger">Eliminar</button>
</form>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
Now that should work.

flask flash() as table rows() with style="display:none" - can't figure out a good way to do this

I have a webapp that renders a table of content. Content to be rendered in returned from a backend and Jinja2 is used to cycle through the data to put into appropriate columns and rows. This part works exactly as I expect. A web user performs some operation with data at each row using some buttons on each row.
In case the backend needs to display messages, I use flash(), with the message(s) rendered at the end of the table. Again, as constructed this works as I expect.
However, as the number of rows of the table grow, the place where messages are flash()'d wind up scrolling off the screen. So I was wondering if I could render flash()'d messages at each row. The intent is that the user receives messages as needed directly under each "affected" row.
The main challenge is to hide the message rows until a message needs to be rendered, and I am not 100% sure how best to do that.
An alternative I was considering is to not use flash(), but deliver additional content as needed for "message" rows. I guess I still have the challenge of checking if anything needs to be rendered at a particular row, and how best to do that...
Here's my current HTML:
<table class="styled-table">
<thead>
<tr>
<th>
Filename
</th>
<th width="70%">
Content
</th>
<th>
id
</th>
<th></th> <!-- edit file button -->
<th></th> <!-- delete file button -->
</tr>
</thead>
<tbody>
{% for content in filesContent %}
<tr>
<td>
<!-- file name -->
<div>
{{ content[2] }}
</div>
</td>
<td>
<!-- file content -->
{{ content[3] }}
</div>
</td>
<td>
<div>
{{ content[1] }}
</div>
</td>
<td>
<td>
<!-- edit button -->
<div>
<a id="{{ content[2] }}" href="/editFile/{{ content[2] }}"><img
src="{{ url_for('static', filename='images/edit_small.png') }}"
alt="edit"></a>
</div>
</td>
<td>
<!-- delete button -->
<div>
<a id="{{ content[2] }}" href="/deleteFile/{{ content[2] }}"><img
src="{{ url_for('static', filename='images/trash_small.png') }}"
alt="delete"></a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
<!--
The backend script returns messages using flash().
-->
<div class="fromBackEnd">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for message in messages %}
{% if "Error" not in message: %}
<div class="alert alert-info">
{{ message[1] }}
</div>
{% endif %}
{% if "Error" in message: %}
<div class="alert alert-warning">
{{ message[1] }}
</div>
{% endif %}
{% endfor %}
{% endif %}
{% endwith %}
</div>
What I'd like to be to do is something like (HTML simplified for brevity):
<table>
{% for content in filesContent %}
<tr>
... my current td content ...
<tr>
<!-- NEW MESSAGE ROWS TO BE DISPLAYED ONLY IF 'messageContent' not null -->
<tr id="<SOMEUNIQUEID>" style="display:none">
<!-- span across all columns -->
<td>
{{ messageContent }}
</td>
</tr>
{% endfor %}
</table>
This way, messages are rendered right under the "affected" row, and easier for users to see. I could use some javascript to change the display style, but maybe I could just use {% if... %} around the tr??
Any guidance would be greatly appreciated!!!

How to avoid duplicate data in Django Template

I have this piece of code :
{% extends 'base.html' %}
{% load static %}
{% block page_title %}Manage Staff{% endblock page_title %}
{% block content %}
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">Manage All Staff</h3>
</div>
<!-- /.card-header -->
<div class="card-body">
<table id="example2" class="table table-bordered table-hover">
<thead>
<tr>
<th>SN</th>
<th>Full Name</th>
<th>Email</th>
<th>Course</th>
</tr>
</thead>
<tbody>
{% for staff in allStaff %}
<tr>
<td>-</td>
<td>{{staff.last_name}}, {{staff.first_name}}</td>
<td>{{staff.email}}</td>
<td>{{staff.course.name}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</section>
{% endblock content %}
The block page_title is used to display the current page in base.html.
My question is, how can I avoid repeating the text "Manage Staff" ?
Is there a way to display the block page_title in this current file ?
What I earlier tried was passing the value from my views.py file, so I wanna be sure I am doing the right thing

How to pass multiple parameters from 'if condition' to 'for loop' in Django?

I have the following code :
{% if sr %}
{% for lap in filter.qs|slice:":20" %}
<tr >
<td class="col-sm-3">
<div >
<div class="product-image-wrapper">
<div class="single-products">
<div class="productinfo text-center">
<img src="{{ lap.product_image }}" alt="" />
</div>
</div>
</div>
</div>
</td>
<td class="col-sm-3">
<h5>{{ lap.product_name }} </h5>
<br>
{# <h5 class="btn btn-outline-secondary"><a href="{{ k.product_url }}" >See Details</a> </h5>#}
<a href="{{ lap.product_url }}" class="btn btn-secondary" role="button" aria-pressed="true"
style="background-color: #3e4e6f; color: white">See Details</a>
</td>
<td class="col-sm-3">{{ lap.product_price }} ৳</td>
<td class="col-sm-3">{{ lap.vendor_name }}</td>
</tr>
{% empty %}
<tr>
<td colspan="5">No data</td>
</tr>
{% endfor %}
{% endif %}
Where I want to pass the parameter sr from if loop to the next for loop along the existing filter.qs|slice:":20" parameter in the following part.
{% if sr %}
{% for lap in filter.qs|slice:":20" %}
How can I pass it? Please help.

Taking Attendance in Django Python

I am trying to mark attendance. But I am not able to get the code. My submit should send the input to database for each student. Any suggestion for doing this in better way is welcome.
My models.py is as follows
It has Employee, Mentor and Student and below is the model where values can be changed.
class ClassName(models.Model):
class_name = models.CharField(max_length=20)
class_date=models.DateField(blank=True, null=True)
Mentor= models.ForeignKey(Mentor, related_name='class_mentor')
student = models.ManyToManyField(Student, related_name='class_student')
attendance = models.BooleanField(default=True)
def __str__(self):
return str(self.class_name)
Views.py : This is just to display the markattendance page. I am not able to figure out how to get the value and Post the value to database. Right now, I am fetching Students value from the Students table. I think I should be creating Classname Form and and display students. I was getting Internal server error.
def markattendance(request):
students = Student.objects.all()
return render(request, 'home/markattendance.html',
{'students': students})
markattendance.html : On clicking submit, the attendance should be marked.
{% extends 'home/index.html' %}
{% block content %}
<div class="container-fluid">
<div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>Name</th>
<th>Class</th>
<th>Attendance</th>
</tr>
</thead>
<tbody>
{% for students in students %}
{% ifequal students.Men_name|stringformat:"s" user.username %}
<tr>
<td>{{ students.Student_name }}</td>
<td>{{ students.Student_Class }}</td>
<td>
<label class="switch">
<input id="toggle-slider_position()" type="checkbox">
<span class="slider round"></span>
</label>
</td>
</tr>
{% endifequal %}
{% endfor %}
</tbody>
</table>
</div>
<br/>
<div class="row" >
<div class="col-sm-4"></div>
<div class='col-sm-4' align="center">
<div class="form-group">
<div class='input-group date' id='datetimepicker1'>
<input type='text' class="form-control" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
<button class="btn btn-lg">Submit</button>
</div>
<div class="col-sm-4">
</div>
</div>
<br/><br/><br/><br/><br/>
</div>
</div>
</div>
{% endblock %}
Please help me out. Any suggestion is welcome.