I have a page in my web app with multiple tables, and rather than have them on separate pages or one long list, I want to use tabs and I need to be able to generate these tabs based on how many objects there are.
I'm pretty certain it's just a problem with the template, but I'll include all the other files just in case.
Here are the models relevant to the problem.
class Exercises(models.Model):
exercise = models.CharField(max_length=45)
evolution = models.CharField(max_length=8)
start_date = models.DateTimeField(blank=True, null=True)
end_date = models.DateTimeField(blank=True, null=True)
logo = models.TextField(blank=True, null=True)
class Meta:
constraints = [
models.UniqueConstraint(
fields=['exercise', 'evolution'], name='exercise_evolution_UNIQUE')
]
def __str__(self):
return f"Exercise: {self.exercise}\t Evolution: {self.evolution}"
class Units(models.Model):
uic = models.CharField(max_length=10)
unit_name = models.CharField(unique=True, max_length=45)
mcc = models.CharField(max_length=5, blank=True, null=True)
ruc = models.CharField(max_length=10, blank=True, null=True)
personnel = models.IntegerField(blank=True, null=True)
class Meta:
constraints = [
models.UniqueConstraint(
fields=['uic', 'mcc', 'ruc'], name='uic_mcc_ruc_UNIQUE')
]
def __str__(self):
return f"{self.unit_name}"
def get_uic(self):
return f'{self.uic}'
class ExercisePersonnel(models.Model):
exercise = models.ForeignKey('Exercises', models.CASCADE)
unit = models.ForeignKey('Units', models.CASCADE)
location = models.ForeignKey('Locations', models.RESTRICT)
quantity = models.IntegerField()
def __str__(self):
return f'{self.unit}'
class UnitEdl(models.Model):
unit = models.ForeignKey('Units', models.CASCADE)
equipment = models.ForeignKey('Equipment', models.CASCADE)
quantity = models.IntegerField()
class Meta:
constraints = [
models.UniqueConstraint(
fields=['unit', 'equipment'], name='unit_equipment_UNIQUE')
I have functions that use database objects to create additional data that shows up in the tables
functions.py
def get_class_one_chow(pax=1, meals_per_day=2):
cases_per_day = pax * meals_per_day / 12
pallets = cases_per_day / 48
short_tons = pallets * 1098 / 2000
twenty_ft_teus = pallets / 16
ugrs_pallets = (pax * 2) / 50 / 8
mres_pallets = pax / 12 / 48
ugrs_short_tons = (ugrs_pallets * 1071 / 2000) + (mres_pallets * 1098 / 2000)
ugr_twenty_ft_teus = (ugrs_pallets + mres_pallets) / 16
return {"cases":round(cases_per_day,1),
"pallets":round(pallets,1),
"short_tons":round(short_tons,1),
"twenty_ft_teus":round(twenty_ft_teus,1),
"ugrs_pallets":round(ugrs_pallets,1),
"mres_pallets":round(mres_pallets,1),
"ugrs_short_tons":round(ugrs_short_tons,1),
"ugr_twenty_ft_teus":round(ugr_twenty_ft_teus,1)
}
def get_class_one_water_bottled(pax=1, planning_factor=2):
min_gallons = pax * planning_factor
min_bottles = (min_gallons * 3.785) * 2
min_cases = min_bottles / 24
min_pallets = min_cases / 72
min_short_tons = min_pallets * 2182 / 2000
twenty_ft_teus = min_pallets / 16
return {"gallons":round(min_gallons,1),
"bottles":round(min_bottles,1),
"cases":round(min_cases,1),
"pallets":round(min_pallets,1),
"short_tons":round(min_short_tons,1),
"twenty_ft_teus":round(twenty_ft_teus,1)
}
def get_class_one_water_bulk(pax=1, planning_factor=1):
min_gallons = pax * planning_factor
min_short_tons = (min_gallons * 8.34) / 2000
return {"gallons":round(min_gallons,1),
"short_tons":round(min_short_tons,1)
}
This is used in the views
def exercise_detail(request, pk, *args, **kwargs):
ex_name = Exercises.objects.get(pk=pk)
ex_personnel = ExercisePersonnel.objects.filter(exercise_id=pk)
planners = ExercisePermissions.objects.filter(exercise=pk)
user_list = MlptUsers.objects.order_by('email')
unit_list_planner = Units.objects.order_by('unit_name')
unit_list, chow_list, bottled_water_list, bulk_water_list = {}, {}, {}, {}
# generate dictionaries so you can parse in template
for unit in ex_personnel:
unit_list[f"{unit}"] = unit.quantity
chow_list[f"{unit}"] = get_class_one_chow(pax=unit.quantity)
bottled_water_list[f"{unit}"] = get_class_one_water_bottled(
pax=unit.quantity)
bulk_water_list[f"{unit}"] = get_class_one_water_bulk(
pax=unit.quantity)
context = {
'ex_name': ex_name,
'chow_list': chow_list,
'bottled_water_list': bottled_water_list,
'bulk_water_list': bulk_water_list,
'unit_list': unit_list,
'planners': planners,
'user_list': user_list,
'unit_list_planner': unit_list_planner,
}
return render(request, 'exercise/exercise_detail.html', context)
However, I can't get the tabs working correctly in the template.
I can create the tables and use a for loop to create a new line for each key in the dictionary "unit_list" which displays all the info, but I don't want it in one place, which looks like this.
<h3>
PLANNING DATA
<small class="text-muted">numbers are per day</small>
</h3>
<ul class="nav nav-tabs" id="myTab" role="tablist">
{% for key,value in unit_list.items %}
<li class="nav-item" role="presentation">
<button class="nav-link active" id="{{key}}-tab" data-bs-toggle="tab" data-bs-target="#{{key}}" type="button" role="tab" aria-controls="home" aria-selected="true"> {{key}} </button>
</li>
{% endfor %}
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="{{key}}" role="tabpanel" aria-labelledby="home-tab">
<div class="row">
<div class="col">
<div class="card text-dark bg-light mb-3" >
<div class="card-header">CLASS I - WATER (BOTTLED)</div>
<div class="card-body">
<table class="table table-striped table-hover table-sm">
<thead class="">
<tr>
<th scope="col text-center">UNIT</th>
<th scope="col text-center">GAL</th>
<th scope="col text-center">BTL</th>
<th scope="col text-center">CASES</th>
<th scope="col text-center">PLTS</th>
<th scope="col text-center">STONS</th>
<th scope="col text-center">20TEUS</th>
</tr>
</thead>
<tbody>
{%for key, value in bottled_water_list.items %}
<tr>
<td class="">{{key}}</td>
<td class="">{{value.gallons}}</td>
<td class="">{{value.bottles}}</td>
<td class="">{{value.cases}}</td>
<td class="">{{value.pallets}}</td>
<td class="">{{value.short_tons}}</td>
<td class="">{{value.twenty_ft_teus}}</td>
</tr>
{%endfor%}
</tbody>
</table>
</div>
</div>
<div class="card text-dark bg-light mb-3" >
<div class="card-header">CLASS I - WATER (BULK)</div>
<div class="card-body">
<table class="table table-striped table-hover table-sm">
<thead class="">
<tr>
<th scope="col">UNIT</th>
<th scope="col">GAL</th>
<th scope="col">STONS</th>
</tr>
</thead>
<tbody>
{%for key, value in bulk_water_list.items %}
<tr>
<td class="">{{key}}</td>
<td class="">{{value.gallons}}</td>
<td class="">{{value.short_tons}}</td>
</tr>
{%endfor%}
</tbody>
</table>
</div>
</div>
<div class="card text-dark bg-light mb-3" >
<div class="card-header">CLASS I - CHOW</div>
<div class="card-body">
<table class="table table-striped table-hover table-sm">
<thead class="">
<tr>
<th scope="col">UNIT</th>
<th scope="col">CASES</th>
<th scope="col">PLTS</th>
<th scope="col">STONS</th>
<th scope="col">20TEUS</th>
<th scope="col">UGR PLTS</th>
<th scope="col">MRE PLTS</th>
<th scope="col">UGR STON</th>
<th scope="col">UGR 20TEUS</th>
</tr>
</thead>
<tbody>
{%for key, value in chow_list.items %}
<tr>
<td class="">{{key}}</td>
<td class="">{{value.cases}}</td>
<td class="">{{value.pallets}}</td>
<td class="">{{value.short_tons}}</td>
<td class="">{{value.twenty_ft_teus}}</td>
<td class="">{{value.ugrs_pallets}}</td>
<td class="">{{value.mres_pallets}}</td>
<td class="">{{value.ugrs_short_tons}}</td>
<td class="">{{value.ugr_twenty_ft_teus}}</td>
</tr>
{%endfor%}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
This is the template and how I've been attempting to accomplish the same thing with separate tabs.
<h3>
PLANNING DATA
<small class="text-muted">numbers are per day</small>
</h3>
<ul class="nav nav-tabs" id="myTab" role="tablist">
{% for key,value in unit_list.items %}
<li class="nav-item" role="presentation">
<button class="nav-link" id="{{key}}-tab" data-bs-toggle="tab" data-bs-target="#{{key}}" type="button" role="tab" aria-controls="{{key}}" aria-selected="true"> {{key}} </button>
</li>
{% endfor %}
</ul>
<div class="tab-content" id="myTabContent">
{% for key,value in unit_list.items %}
<div class="tab-pane fade" id="{{key}}" role="tabpanel" aria-labelledby="{{key}}-tab">
<div class="row">
<div class="col">
<div class="card text-dark bg-light mb-3" >
<div class="card-header">CLASS I - WATER (BOTTLED)</div>
<div class="card-body">
<table class="table table-striped table-hover table-sm">
<thead class="">
<tr>
<th scope="col text-center">UNIT</th>
<th scope="col text-center">GAL</th>
<th scope="col text-center">BTL</th>
<th scope="col text-center">CASES</th>
<th scope="col text-center">PLTS</th>
<th scope="col text-center">STONS</th>
<th scope="col text-center">20TEUS</th>
</tr>
</thead>
<tbody>
<tr>
<td class="">{{key}}</td>
<td class="">{{value.gallons}}</td>
<td class="">{{value.bottles}}</td>
<td class="">{{value.cases}}</td>
<td class="">{{value.pallets}}</td>
<td class="">{{value.short_tons}}</td>
<td class="">{{value.twenty_ft_teus}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card text-dark bg-light mb-3" >
<div class="card-header">CLASS I - WATER (BULK)</div>
<div class="card-body">
<table class="table table-striped table-hover table-sm">
<thead class="">
<tr>
<th scope="col">UNIT</th>
<th scope="col">GAL</th>
<th scope="col">STONS</th>
</tr>
</thead>
<tbody>
<tr>
<td class="">{{key}}</td>
<td class="">{{value.gallons}}</td>
<td class="">{{value.short_tons}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card text-dark bg-light mb-3" >
<div class="card-header">CLASS I - CHOW</div>
<div class="card-body">
<table class="table table-striped table-hover table-sm">
<thead class="">
<tr>
<th scope="col">UNIT</th>
<th scope="col">CASES</th>
<th scope="col">PLTS</th>
<th scope="col">STONS</th>
<th scope="col">20TEUS</th>
<th scope="col">UGR PLTS</th>
<th scope="col">MRE PLTS</th>
<th scope="col">UGR STON</th>
<th scope="col">UGR 20TEUS</th>
</tr>
</thead>
<tbody>
<tr>
<td class="">{{key}}</td>
<td class="">{{value.cases}}</td>
<td class="">{{value.pallets}}</td>
<td class="">{{value.short_tons}}</td>
<td class="">{{value.twenty_ft_teus}}</td>
<td class="">{{value.ugrs_pallets}}</td>
<td class="">{{value.mres_pallets}}</td>
<td class="">{{value.ugrs_short_tons}}</td>
<td class="">{{value.ugr_twenty_ft_teus}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{%endfor%}
</div>
This is the source code of the webpage when I run it.
<h3>
PLANNING DATA
<small class="text-muted">numbers are per day</small>
</h3>
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link" id="31st MEU-tab" data-bs-toggle="tab" data-bs-target="#31st MEU" type="button" role="tab" aria-controls="31st MEU" aria-selected="true"> 31st MEU </button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="7th Comm Bn-tab" data-bs-toggle="tab" data-bs-target="#7th Comm Bn" type="button" role="tab" aria-controls="7th Comm Bn" aria-selected="true"> 7th Comm Bn </button>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade" id="31st MEU" role="tabpanel" aria-labelledby="31st MEU-tab">
<div class="row">
<div class="col">
<div class="card text-dark bg-light mb-3" >
<div class="card-header">CLASS I - WATER (BOTTLED)</div>
<div class="card-body">
<table class="table table-striped table-hover table-sm">
<thead class="">
<tr>
<th scope="col text-center">UNIT</th>
<th scope="col text-center">GAL</th>
<th scope="col text-center">BTL</th>
<th scope="col text-center">CASES</th>
<th scope="col text-center">PLTS</th>
<th scope="col text-center">STONS</th>
<th scope="col text-center">20TEUS</th>
</tr>
</thead>
<tbody>
<tr>
<td class="">31st MEU</td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card text-dark bg-light mb-3" >
<div class="card-header">CLASS I - WATER (BULK)</div>
<div class="card-body">
<table class="table table-striped table-hover table-sm">
<thead class="">
<tr>
<th scope="col">UNIT</th>
<th scope="col">GAL</th>
<th scope="col">STONS</th>
</tr>
</thead>
<tbody>
<tr>
<td class="">31st MEU</td>
<td class=""></td>
<td class=""></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card text-dark bg-light mb-3" >
<div class="card-header">CLASS I - CHOW</div>
<div class="card-body">
<table class="table table-striped table-hover table-sm">
<thead class="">
<tr>
<th scope="col">UNIT</th>
<th scope="col">CASES</th>
<th scope="col">PLTS</th>
<th scope="col">STONS</th>
<th scope="col">20TEUS</th>
<th scope="col">UGR PLTS</th>
<th scope="col">MRE PLTS</th>
<th scope="col">UGR STON</th>
<th scope="col">UGR 20TEUS</th>
</tr>
</thead>
<tbody>
<tr>
<td class="">31st MEU</td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="7th Comm Bn" role="tabpanel" aria-labelledby="7th Comm Bn-tab">
<div class="row">
<div class="col">
<div class="card text-dark bg-light mb-3" >
<div class="card-header">CLASS I - WATER (BOTTLED)</div>
<div class="card-body">
<table class="table table-striped table-hover table-sm">
<thead class="">
<tr>
<th scope="col text-center">UNIT</th>
<th scope="col text-center">GAL</th>
<th scope="col text-center">BTL</th>
<th scope="col text-center">CASES</th>
<th scope="col text-center">PLTS</th>
<th scope="col text-center">STONS</th>
<th scope="col text-center">20TEUS</th>
</tr>
</thead>
<tbody>
<tr>
<td class="">7th Comm Bn</td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card text-dark bg-light mb-3" >
<div class="card-header">CLASS I - WATER (BULK)</div>
<div class="card-body">
<table class="table table-striped table-hover table-sm">
<thead class="">
<tr>
<th scope="col">UNIT</th>
<th scope="col">GAL</th>
<th scope="col">STONS</th>
</tr>
</thead>
<tbody>
<tr>
<td class="">7th Comm Bn</td>
<td class=""></td>
<td class=""></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card text-dark bg-light mb-3" >
<div class="card-header">CLASS I - CHOW</div>
<div class="card-body">
<table class="table table-striped table-hover table-sm">
<thead class="">
<tr>
<th scope="col">UNIT</th>
<th scope="col">CASES</th>
<th scope="col">PLTS</th>
<th scope="col">STONS</th>
<th scope="col">20TEUS</th>
<th scope="col">UGR PLTS</th>
<th scope="col">MRE PLTS</th>
<th scope="col">UGR STON</th>
<th scope="col">UGR 20TEUS</th>
</tr>
</thead>
<tbody>
<tr>
<td class="">7th Comm Bn</td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
So none of the data populates into the tables when I use the for loop in this way and the html for the tables is greyed out when I inspect it, and clicking the tabs does not make it appear.
It looks like thisenter image description here
I believe this means I am somehow not successfully linking the tab id to the tab content id even though the ids match and I also don't know how the context is passed when I run the for loop on individual tables, but not the whole thing.