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)
Related
How do I pass the value from the inside of a for loop ( jinja2 ) to a bootstrap modal to display it in side the modal body?
here is my views.py file:
if request.method == 'GET':
driver = get_network_driver(device.napalm_driver)
with driver(device.IP_address, device.username, device.password) as device_conn:
interfaces = device_conn.get_interfaces()
context = {
'device': device,
'interfaces': interfaces,
}
return render(request, 'network/interface_list.html', context)
Please note that the the device_conn.get_interfaces() method returns a nested dictionary.
Here is the html template:
{% extends 'base/base.html' %}
{% block title %}iNet Interface List{% endblock %}
{% block content %}
<div class="section">
{% include 'network/include/interface_list_header.html' %}
{% if messages %}
{% for message in messages %}
{% if message.tags == 'success' %}<div class="alert alert-success" role="alert">
{{ message }}
</div>{% elif message.tags == 'error' %}<div class="alert alert-danger" role="alert">
{{ message }}
</div>{% endif %}
{% endfor %}
{% endif %}
<div class="card mx-auto shadow rounded">
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<th scope="col" style="text-align:center">Interface Name</th>
<th scope="col" style="text-align:center">Admin status</th>
<th scope="col" style="text-align:center">Protocol</th>
<th scope="col" style="text-align:center">Description</th>
<th scope="col" style="text-align:center">MAC Address</th>
<th scope="col" style="text-align:center">Last Flapped</th>
<th scope="col" style="text-align:center">Turn On/Off Port</th>
<th scope="col" style="text-align:center">Edit Description</th>
</tr>
</thead>
<tbody>
{% for interface_name, interface in interfaces.items %}
<tr>
<form action="{% url 'get_interfaces' device.id %}" method="post" id="{{ interface_name }}">
{% csrf_token %}
<input type="hidden" value="{{ interface_name }}" name="interface_name" />
<input type="hidden" value="{{ interface.is_enabled|yesno:'False,True' }}" name="enable" />
</form>
<td style="text-align:center">{{ interface_name }}</td>
<td style="text-align:center">{% if interface.is_enabled %}<i class="fa-solid fa-check text-success"></i>{% else %}<i class="fa-solid fa-xmark text-danger"></i>{% endif %}</td>
<td style="text-align:center">{% if interface.is_up %}<i class="fa-solid fa-check text-success"></i>{% else %}<i class="fa-solid fa-xmark text-danger"></i>{% endif %}</td>
<td style="text-align:center">{{ interface.description }} </td>
<td style="text-align:center">{{ interface.mac_address }}</td>
<td style="text-align:center">{{ interface.last_flapped }}</td>
<td style="text-align:center"><button class="btn common-button btn-primary" type="submit" form="{{ interface_name }}" value="Submit">{% if interface.is_enabled %}Turn Off{% else %}Turn On{% endif %}</button></td>
<!-- Modal Trigger button -->
<td style="text-align:center"><i class="fa-regular fa-clipboard"></i></td>
<!-- Modal container -->
<div class="modal fade viewModal" id="editDesc{{ interface_name }}" tabindex="-1" role="dialog" aria-labelledby="editDescLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 style="font-size: 20px;" class="modal-title" id="editDescLabel">View Console Output</h5>
<button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<textarea>{{ interface.description }}</textarea>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endblock %}
I wish to show the {{interface.description}} of the selected interface in the textarea so that I can edit it later. Any help would be appreciated.
My issue is - I am able to fetch {{interface.description}} outside the bootstrap modal, however I am unable to fetch the same thin inside the bootstrap modal. Eventhough both of them are inside the for loop.
I'm trying to submit Django forms in Bootstrap 4 modals with AJAX, but it doesnt submit for some reason. When you click on the submit button it just closes the modal and nothing else happens. The content shows correctly in the modal body at least, but it just doesnt submit.
Here is my view
class GaasWaferDesignFormView(SuccessMessageMixin, AjaxTemplateMixin, CreateView):
template_name = 'engineering/gaas_wafer_designs/gaas_wafer_design_form.html'
ajax_template_name = 'engineering/gaas_wafer_designs/gaas_wafer_design_form_inner.html'
form_class = GaasWaferDesignForm
model = GaasWaferDesign
form = GaasWaferDesignForm()
success_url = reverse_lazy('engineering:gaas_wafer_design_list')
success_message = "Success!"
def form_valid(self, form):
object = form.save(commit=False)
object.created_by = self.request.user
object.save()
return super(GaasWaferDesignCreateView, self).form_valid(form)
And here is my template which has the modal structure and button for the modal(gaas_wafer_design_list.html)...
{% extends "pages/list_template.html" %}{% load static from staticfiles %}
{% load widget_tweaks %}
{% block title %}GaAs Wafer Design List{% endblock %}
{% block list_title %}GaAs Wafer Designs{% endblock %}
{% block list_title_2 %}Design Inventory{% endblock %}
{% block extra_js%}
{% endblock %}
{% block buttons %}
<div class="btn-group" role="group" aria-label="Button group with nested dropdown" style="margin-bottom: -150px; z-index:1000;">
<button class="btn btn-secondary" data-toggle="modal" data-target="#form-modal" id="create-button">Create a new wafer design</button>
<div class="btn-group" role="group">
<a id="btnGroupDrop1" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
View
</a>
<div class="dropdown-menu" aria-labelledby="btnGroupDrop1">
<a class="dropdown-item" href="#">Recycling Bin</a>
</div>
</div>
</div>
{% endblock %}
{% block table %}
<div class="modal fade" id="form-modal" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Add Wafer Design</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
<span class="sr-only">Close</span>
</button>
</div>
<div id="form-modal-body" class="modal-body">
</div>
</div>
</div><!-- /.modal-dialog -->
</div>
<thead>
<tr>
<th>
Wafer Design UI
</th>
<th>
Emitting Type
</th>
<th>
Contact Location
</th>
<th>
Optical Power
</th>
<th>
Design Date
</th>
<th>
Designer
</th>
<th>
Designer UI
</th>
<th>
Created At
</th>
</tr>
</thead>
<tfoot>
<tr>
<th>
Wafer Design UI
</th>
<th>
Emitting Type
</th>
<th>
Contact Location
</th>
<th>
Optical Power
</th>
<th>
Design Date
</th>
<th>
Designer
</th>
<th>
Designer UI
</th>
<th>
Created At
</th>
</tr>
</tfoot>
<tbody>
{% for gaas_wafer_design in gaas_wafer_designs %}
<tr>
<td>{{ gaas_wafer_design.design_ui }}</td>
<td>{{ gaas_wafer_design.get_emitting_display }}</td>
<td>{{ gaas_wafer_design.contact_location }}</td>
<td>{{ gaas_wafer_design.optical_power }}</td>
<td>{{ gaas_wafer_design.design_date|date:"m/d/y" }}</td>
<td>{{ gaas_wafer_design.designer }}</td>
<td>{{ gaas_wafer_design.designer_ui }}</td>
<td>{{ gaas_wafer_design.created_at }}</td>
</tr>
{% endfor %}
</tbody>
<script>
var formAjaxSubmit = function(form, modal) {
$(form).submit(function (e) {
e.preventDefault();
$.ajax({
type: $(this).attr('method'),
url: $(this).attr('action'),
data: $(this).serialize(),
success: function (xhr, ajaxOptions, thrownError) {
if ( $(xhr).find('.has-error').length > 0 ) {
$(modal).find('.modal-body').html(xhr);
formAjaxSubmit(form, modal);
} else {
$(modal).modal('toggle');
}
},
error: function (xhr, ajaxOptions, thrownError) {
// handle response errors here
}
});
});
}
$('#create-button').click(function() {
$('#form-modal-body').load('create/', function () {
$('#form-modal').modal('toggle');
formAjaxSubmit('#form-modal-body form', '#form-modal');
});
});
</script>
{% endblock %}
Here is my url...
url(r'^gaas-wafer-designs/create/$', gaas_wafer_designs.GaasWaferDesignFormView.as_view(), name='gaas_wafer_design_create'),
And lastly here is my gaas_wafer_design_form_inner.html (template which has the modal body content)
{% load widget_tweaks %}
<form method="post" action="{% url 'engineering:gaas_wafer_design_create' %}">{% csrf_token %}
<div class="row">
<div class="form-group col-sm-12">
<div class="form-group">
<label for="{{ form.design_ui.id_for_label }}"><b>Design UI</b></label>
{% render_field form.design_ui class+="form-control" %}
{{ form.design_ui.errors }}
</div>
</div>
</div>
<!--/.row-->
<div class="row">
<div class="form-group col-sm-4">
<div class="form-group">
<label for="{{ form.emitting.id_for_label }}"><b>Emitting</b></label>
{% render_field form.emitting class+="form-control" %}
{{ form.emitting.errors }}
</div>
</div>
<div class="form-group col-sm-4">
<div class="form-group">
<label for="{{ form.contact_location.id_for_label }}"><b>Contact Location</b></label>
{% render_field form.contact_location class+="form-control" %}
{{ form.contact_location.errors }}
</div>
</div>
<div class="form-group col-sm-4">
<div class="form-group">
<label for="{{ form.optical_power.id_for_label }}">Optical Power</label>
{% render_field form.optical_power class+="form-control" %}
{{ form.optical_power.errors }}
</div>
</div>
</div>
<!--/.row-->
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<input type="submit" class="btn btn-primary" value="Save changes" />
</form>
Thanks for any help you can give!
I believe that the object is created, but your form_valid doesn't return to the success_url. At the end of your form_valid you should redirect to success_url. I don't understand what you're trying to achieve with your return at the end of form_valid.
def form_valid(self, form):
...
return HttpResponseRedirect(self.get_success_url())
And you can than also override success_url and add massage if needed.
def get_success_url(self):
# add message
messages.add_message(self.request, messages.SUCCESS, 'Your message.')
# reverse back to providers' page with success message
return reverse_lazy('engineering:gaas_wafer_design_list')
I have written a simple to use package for such functionalities and you can check it out at django-bootstrap-modal-forms.
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">
I have a registration page for teachers having fields like email, mobile number, password etc, the table is named as Teacher.
I want to login page too for the same.
What I am doing is:
Added following in url page:
url(r'^login/$', auth_views.login, {'template_name': 'login.html'},name='login'),
Added following in settings.py:
AUTH_USER_MODEL = 'myapp.Teacher'
Added login.html:
{% extends "base.html" %}
{% load widget_tweaks %}
{% block body_block %}
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
{% if next %}
{% if user.is_authenticated %}
<p>Your account doesn't have access to this page. To proceed,
please login with an account that has access.</p>
{% else %}
<p>Please login to see this page.</p>
{% endif %}
{% endif %}
<div class="container">
<div class="row">
<div class="col-md-4 col-md-offset-4">
<div class="login-panel panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Please Sign In</h3>
</div>
<div class="panel-body">
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<p class="bs-component">
<table>
<tr>
<td>{{ form.username.label_tag }}</td>
<td>{{ form.username }}</td>
</tr>
<tr>
<td>{{ form.password.label_tag }}</td>
<td>{{ form.password }}</td>
</tr>
</table>
</p>
<p class="bs-component">
<center>
<input class="btn btn-success btn-sm" type="submit" value="login" />
</center>
</p>
<input type="hidden" name="next" value="{{ next }}" />
</form>
</div>
</div>
</div>
</div>
</div>
{%endblock body_block%}
Now the login page doesn't work, giving me error:
AttributeError: type object 'Teacher' has no attribute 'REQUIRED_FIELDS'
How can I implement custom login page in django?
I'm trying to make a webpage that will display recipes in the format of a bootstrap accordion like so (see here).
This is how I'm doing it as of now:
<div class="panel-group" id="accordion">
{% for recipe in recipes %}
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapse{{ forloop.counter }}">
{{ recipe }}
</a>
</h4>
</div>
<div id="collapse{{ forloop.counter }}" class="panel-collapse collapse">
<div class="panel-body">
<table class="table table-hover">
{% for ingredient in foodtype|ingredients_in_recipe:recipe %}
<tr>
<td>
{{ ingredient.ingredient_name }}
</td>
<td>
{{ ingredient.ingredient_quantity }}
</td>
</tr>
{% endfor %}
<p>{{ recipe.details }}</p>
</table>
</div>
</div>
</div>
{% endfor %}
</div>
I have made a custom template tag for this like so:
#register.filter
def ingredients_in_recipe(foodtype, recipe):
return foodtype.ingredient_set.filter(recipe=recipe).order_by("ingredient_name")
The problem is that I have 200+ recipes and loading all this data is way too slow. Ideally the template tag function ingredients_in_recipe should only be called when the user clicks on the recipe. However from my understanding this isn't possible because Django runs it all then sends the rendered HTML to the user.
Is there anyway I could circumvent this issue whilst still keeping the accordion style like in the picture?
Thanks in advance,
Max
EDIT: Here's my view as well
def detail(request, foodtype_id):
foodtype = get_object_or_404(foodtype, id=foodtype_id)
recipe = foodtype.recipe_set.values_list('recipe').order_by('recipe').distinct()
context = {
'foodtype': foodtype,
'recipe': recipe,
}
return render(request, 'main/detail.html', context)
Always better to do that logic before it gets to the template. What if you set the ordering on ingredients so then you won't have to order them in the template? Does that work and improve the performance?
class Ingredient(models.Model):
...
class Meta:
ordering = ['ingredient_name']
<div class="panel-group" id="accordion">
{% for recipe in recipes %}
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapse{{ forloop.counter }}">
{{ recipe }}
</a>
</h4>
</div>
<div id="collapse{{ forloop.counter }}" class="panel-collapse collapse">
<div class="panel-body">
<table class="table table-hover">
{% for ingredient in recipe.ingredient_set.all %}
<tr>
<td>
{{ ingredient.ingredient_name }}
</td>
<td>
{{ ingredient.ingredient_quantity }}
</td>
</tr>
{% endfor %}
<p>{{ recipe.details }}</p>
</table>
</div>
</div>
</div>
{% endfor %}
</div>