I'm having a 2 models Zone and DailyTask So I want to make a table in the front end(HTML)
that like image is shown below. U is used_tasks UN is unused_tasks T total_tasks
I want list this data for each zones for the currusponding timeslots this is my current code
model one Zone
class DailyTask(models.Model):
date = models.DateField()
zone = models.ForeignKey(Zone, on_delete=models.SET_NULL, null=True)
slot = models.ForeignKey(GeneralTimeSlot,related_name='daily_task', on_delete=models.CASCADE)
total_tasks = models.IntegerField(default=0)
used_tasks = models.IntegerField(default=0)
unused_tasks = models.IntegerField(default=0)
available_driver_slots = models.ManyToManyField(DriverTimeSlot)
model two Zone
class Zone(models.Model):
name = models.CharField(max_length=200)
coordinates = models.TextField(null=True, blank=True)
time slot view.py
def get(self, request, *args, **kwargs):
zones = Zone.objects.all()
today = datetime.date.today()
daily_task = DailyTask.objects.filter(date="2022-06-04")
return render(request, self.template_name, {'zones': zones, 'daily_tasks': daily_task})
template timeslotreport.html
{% extends 'macro-admin/base.html' %}
{% load crispy_forms_tags %}
{% block title %}
<title>Time Slot Report</title>
{% endblock %}
{% block content %}
<style type="text/css">
table {
border-collapse: collapse;
width: 100%;
}
td, th {
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
.button1 button{
border: 2px solid #3783b5;
border-radius: 5px;
padding: 5px 15px;
margin: 2px 0;
background-color: white;
width: 80px;
}
.under{
text-decoration:underline;
}
.order2 .card-title{
font-size: 25px!important;
}
.order2 button{
float: right;
padding: 10px 80px!important;
}
.marg{
padding-top: 50px;
}
.marg .row{
padding: 10px;
border-bottom: 1px solid #ece4e4;
}
.settle h4{
float: right;
padding: 5px 20px;
border: 2px solid #3783b5;
border-radius: 10px;
font-size: 15px;
}
.settle2 h4{
float: left;
padding: 5px 20px;
border: 2px solid #3783b5;
border-radius: 10px;
font-size: 15px;
}
input#birthday {
padding: 8px 10px!important;
min-width: 144px!important;
margin: 0 10px!important;
border-radius: 5px!important;
border: 1px solid #3f57ff!important;
background: #3f57ff!important;
color-scheme: dark!important;
}
</style>
<div class="container-fluid">
<div class="card" >
<div class="card-header order2">
<a class="card-title">
Time Slot Report
</a>
</div>
</div>
<div class="col-lg-12 col-md-12">
<div class="row my-2">
<div class="col-12 d-flex justify-content-md-center sort-index">
<form class="form-inline" action="/action_page.php">
<input type="date" id="birthday" name="birthday">
</form>
</div>
</div>
</div>
<hr>
<div class="card">
<!--<div class="card-header">
<h4 class="card-title">
Default
</h4>
</div> -->
<div class="card-body">
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Time Slots</th>
{% for z in zones %}
<th scope="col">{{ z.name }}</th>
{% endfor %}
<th scope="col">Total used</th>
<th scope="col">Total unused</th>
<th scope="col">Total</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="col"></th>
{% for z in zones %}
<th scope="col">U / Un / T</th>
{% endfor %}
<th scope="col"></th>
<th scope="col"></th>
<th scope="col"></th>
</tr>
{% for zone in zones|slice:":1" %}
{% for task in daily_tasks %}
{% if task.zone.id == zone.id %}
<tr>
<th class="align-middle text-center" scope="row">{{ task.slot.start_time.time }} - {{ task.slot.end_time.time }}</th>
{% for zo in zones %}
{% if task.zone.id == zone.id %}
<td class="align-middle text-center">{{ task.used_tasks }} / {{ task.unused_tasks }} / {{ task.total_tasks }}</td>
{% endif %}
{% endfor %}
</tr>
{% endif %}
{% endfor %}
{% endfor %}
</tbody>
</table>
</div>
</div>
<th class="align-middle text-center" scope="row">08:00:00AM - 09:00:00AM</th>
</tr>
<tr>
<th class="align-middle text-center" scope="row">09:00:00AM - 10:00:00AM</th>
</tr>
<tr>
<th class="align-middle text-center" scope="row">10:00:00AM - 11:00:00AM</th>
<td class="align-middle text-center">
{% for zone in zones %}
{% if zone.name == "Zone A" %}
{{ zone }}
{% endif %}
{% endfor %}
</td>
</tr>
<tr>
<th class="align-middle text-center" scope="row">12:00:00PM - 01:00:00PM</th>
</tr>
<tr>
<th class="align-middle text-center" scope="row">04:00:00PM - 05:00:00PM</th>
</tr>
<tr>
<th class="align-middle text-center" scope="row">05:00:00PM - 06:00:00PM</th>
</tr>
<tr>
<th class="align-middle text-center" scope="row">06:00:00PM - 07:00:00PM</th>
</tr>
<tr>
<th class="align-middle text-center" scope="row">07:00:00PM - 08:00:00PM</th>
</tr>
<tr>
<th class="align-middle text-center" scope="row">08:00:00PM - 09:00:00PM</th>
</tr>
<tr>
<th class="align-middle text-center" scope="row">09:00:00PM - 10:00:00PM</th>
</div>
<div class="card-body bg-fade">
<div class="d-flex align-items-center justify-content-center">
<nav aria-label="Page navigation" class="mr-3">
<ul class="pagination m-0">
<li class="page-item">
<a class="page-link" href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
<span class="sr-only">Previous</span>
</a>
</li>
<li class="page-item active"><a class="page-link" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item">
<a class="page-link" href="#" aria-label="Next">
<span aria-hidden="true">»</span>
<span class="sr-only">Next</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
the result i want is data on this image
When rendering a new page, the html form action on that new page is stopping the page from being rendered... even though it has nothing to do with the page itself being rendered (if I remove that one line of HTML code, the page loads just fine). I've been working on solving this problem for over 3 days, tried hundreds of possible solutions, nothing works. Please help
This is the error:
NoReverseMatch at /newgallery/rodneyadmin
Reverse for 'editgallery' with arguments '('rodneyadmin', '')' not found. 1 pattern(s) tried: ['editgallery/(?P<username>[^/]+)/(?P<new_gallery>[0-9]+)\\Z']
Request Method: GET
Request URL: http://127.0.0.1:8000/newgallery/rodneyadmin
Django Version: 4.0
Exception Type: NoReverseMatch
Exception Value:
Reverse for 'editgallery' with arguments '('rodneyadmin', '')' not found. 1 pattern(s) tried: ['editgallery/(?P<username>[^/]+)/(?P<new_gallery>[0-9]+)\\Z']
Exception Location: /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/django/urls/resolvers.py, line 729, in _reverse_with_prefix
Python Executable: /Library/Frameworks/Python.framework/Versions/3.9/bin/python3
Python Version: 3.9.7
Python Path:
['/Users/rodneyrussell/Desktop/github/Capstone/Capstone',
'/Library/Frameworks/Python.framework/Versions/3.9/lib/python39.zip',
'/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9',
'/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/lib-dynload',
'/Users/rodneyrussell/Library/Python/3.9/lib/python/site-packages',
'/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages']
Server time: Thu, 10 Feb 2022 16:41:21 -0500
Error during template rendering
In template /Users/rodneyrussell/Desktop/github/Capstone/Capstone/templates/galleries/newgallery.html, error at line 21
Reverse for 'editgallery' with arguments '('rodneyadmin', '')' not found. 1 pattern(s) tried: ['editgallery/(?P<username>[^/]+)/(?P<new_gallery>[0-9]+)\\Z']
11 Create new gallery
12 </h1>
13 </div>
14 </div>
15
16
17 <div class="row mb-3 d-flex justify-content-center">
18
19 <div class="col-lg-4 col-med-8 col-sm-8 text-primary" style="height: fit-content;">
20
21 <form action="{% url 'gallery_app:editgallery' user.username new_gallery.id %} " style="font-weight: bolder;" enctype='multipart/form-data' method='POST' class='gap-2'>
22
23 {% csrf_token %}
24
25
26 <div class="form-group mb-5">
27 <label style="margin-right: 20px;">Public Gallery</label>
28 {{form.public_gallery}}
29 </div>
30
31 <div class="form-group mb-5">
This is the line of code being highlighted as cause for error (form action):
<form action="{% url 'gallery_app:editgallery' user.username new_gallery.id %} " style="font-weight: bolder;" enctype='multipart/form-data' method='POST' class='gap-2'>
Views.py:
#login_required
def newgallery(request, username):
if request.method == 'GET':
form = NewGalleryForm
context = {
'form': form,
'username': username,
}
return render(request, 'galleries/newgallery.html', context)
def editgallery(request, username):
if request.method == "POST":
form = NewGalleryForm(request.POST)
if form.is_valid():
new_gallery = form.save(commit = False)
## connect the new gallery with the user (foreign key)
new_gallery.user = request.user
new_gallery.save()
url = "https://api.opensea.io/api/v1/assets?order_direction=desc&offset=0&limit=5"
params={'owner': new_gallery.wallett_address}
headers = {
"Accept": "application/json",
"X-API-KEY": ""
}
response = requests.request("GET", url, headers=headers, params=params)
response = response.json()["assets"]
list_of_nfts = []
for dictionary in response:
token_id = dictionary["token_id"]
token_address = dictionary["asset_contract"]["address"]
contract_address = 'https://api.opensea.io/api/v1/asset/' + token_address + '/' + token_id + '/'
name = dictionary["name"]
if len(name) > 50:
name = (name[:50] + '...')
nft_created_date = dictionary["asset_contract"]["created_date"]
nft_created_date = nft_created_date[:10]
nft_created_date = datetime.strptime(nft_created_date, '%Y-%m-%d').strftime('%m/%d/%Y')
image = dictionary["image_url"]
description = dictionary["description"]
if description is not None and '*' in description:
head, sep, tail = description.partition('*')
description = head
if description is not None and len(description) > 50:
description = (description[:150] + '...')
if isinstance(description, str) != True:
description = 'No description provided'
link = dictionary["permalink"]
nft_dict = {
'contract_address': contract_address,
'name': name,
'image': image,
'description': description,
'link': link,
'nft_created_date': nft_created_date,
}
list_of_nfts.append(nft_dict)
context = {
'new_gallery': new_gallery,
'list_of_nfts': list_of_nfts,
'raw_nft_data': json.dumps(list_of_nfts),
'new_gallery_name': new_gallery.gallery_name,
'user': new_gallery.user,
username:username,
}
return render(request, 'galleries/editgallery.html', context)
New Gallery HTML (page where user enters basic information regarding New Gallery that he or she is creating... when this form is submitted, the user is brought to a page where they can edit the gallery that was just created (by edit, I mean add new NFT's to that gallery):
<div class="row mb-3">
<div class="col-lg-12 col-sm-12 text-primary d-flex justify-content-center align-items-center">
<h1
class="homepagetitle mt-4 mb-5"
style="font-size: 2.4rem; color: rgb(231, 114, 208)"
>
Create new gallery
</h1>
</div>
</div>
<div class="row mb-3 d-flex justify-content-center">
<div class="col-lg-4 col-med-8 col-sm-8 text-primary" style="height: fit-content;">
<form action="{% url 'gallery_app:editgallery' user.username new_gallery.id %} " style="font-weight: bolder;" enctype='multipart/form-data' method='POST' class='gap-2'>
{% csrf_token %}
<div class="form-group mb-5">
<label style="margin-right: 20px;">Public Gallery</label>
{{form.public_gallery}}
</div>
<div class="form-group mb-5">
<label>Gallery Name </label>
{{form.gallery_name}}
</div>
<div class="form-group mb-5">
<label>Wallett Address</label>
<span class="hovertext" style="color: rgb(231, 114, 208); font-weight: normal;" data-hover="You will be adding NFT's from this wallet. Max wallet size: 50 NFT's">?</span>
{{form.wallett_address}}
</div>
<div class="form-group mb-5">
<label style="margin-right: 20px;">Category </label>
{{form.gallery_category}}
</div>
<button
type="submit"
class="btn btn-dark mt-4 mb-4"
style="
font-size: 1.1rem;
height: 50px;
width:fit-content;
"
>
Add NFT's   <i class="far fa-arrow-alt-circle-right"></i>
</button>
</form>
</div>
</div>
User Profile HTML (page where user clicks on an a tag to bring them to the the New Gallery HTML (the other HTML I have listed above). That is when the code breaks and gives that error. The url in that a tag is href="{% url 'gallery_app:newgallery' user.username %}":
<h1 class="homepagetitle mt-4 mb-5 d-flex justify-content-center align-items-center" style="font-size: 2.4rem; color: rgb(231, 114, 208);">
Hello 
<span style="font-size: 2.4rem; color: rgb(231, 114, 208);"
>{{user.username}} <i class="far fa-hand-paper" style="font-size: 2.4rem; color: rgb(231, 114, 208);"></i></span
>
</h1>
{% endif %}
<div class="row col-12">
<div class="col-lg-6">
<div class="pt-3 profile-image">
<img
src="{% static user.avatar.url %}"
alt="{{user.username}}'s avatar"
class="rounded-circle shadow"
height="300"
width="275"
/>
</div>
{% if request.user == user %}
<span>
<div class="editicon">
<a
href="{% url 'users_app:update' user.username %}"
style="
color: rgb(226, 81, 197);
-webkit-text-stroke: 1px black;
text-decoration: none;
"
>
<i class="fas fa-user-edit"></i>
</a>
</div>
</span>
{% endif %}
<!-- 'users_app:update' user.username -->
<table class="table profile-margin">
<tbody>
{% if request.user == user %}
<tr>
<th scope="row"></th>
<td>Name:</td>
<td>{{user.first_name}} {{user.last_name}}</td>
</tr>
<tr>
<th scope="row"></th>
<td>Email:</td>
<td>{{user.email}}</td>
</tr>
{% endif %}
<tr>
<th scope="row"></th>
<td>Username:</td>
<td>{{user.username}}</td>
</tr>
<tr>
<th scope="row"></th>
<td>Profile created:</td>
<td>{{user.date_joined|date}}</td>
</tr>
<tr>
<th scope="row"></th>
<td>Galleries:</td>
<td>0</td>
</tr>
<tr>
<th scope="row"></th>
<td>Followers:</td>
<td>0</td>
</tr>
<tr>
<th scope="row"></th>
<td>Following:</td>
<td>0</td>
</tr>
</tbody>
</table>
</div>
<div class="col-lg-6">
{% if request.user.is_authenticated %}
<h3 class=" d-flex homepagetitle" style="justify-content:center; margin-top: 30px; margin-bottom: 0px; padding:10px; height: 75px; font-size: 2.2rem; color: rgb(231, 114, 208);">
<i><a class="homepagetitle far fa-plus-square" href="{% url 'gallery_app:newgallery' user.username %}" style="text-decoration: none; font-size: 2.2rem; color: rgb(231, 114, 208); position:relative; left: -70px; font-size: 2rem;"></i></a>
Your Galleries:
</h3>
{% else %}
<h3 class=" d-flex justify-content-center homepagetitle" style="margin-top: 30px; margin-bottom: 0px; padding:10px; height: 75px; font-size: 2.2rem; color: rgb(231, 114, 208);">
{{user.username}}'s Galleries:
</h3>
{% endif %}
<div class='user-galleries d-flex justify-content-center' style="background-color: rgb(247, 229, 243); border-radius: 8px;">
<div class="gallery-posts py-3">
<table class="table profile-margin" style="color:rgb(231, 114, 208); font-weight: bolder;">
<tbody>
{% for gallery in user.newgallery.all %}
<tr>
<th scope="row"></th>
<td>{{ gallery.gallery_name }}</td>
<td>NFT's: 0</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
Urls.py:
app_name = 'gallery_app'
urlpatterns = [
path('newgallery/<str:username>', views.newgallery, name='newgallery'),
path('editgallery/<str:username>/<int:gallery_id>', views.editgallery, name='editgallery'),
path('galleryview/<str:username>/<int:gallery_id>', views.galleryview, name='galleryview'),
]
It looks like the url argument new_gallery.id is empty when you render the html template.
update: so the template is called from view newgallery.
In your original code there is 2 things to change:
to instantiate the form please add () after NewGalleryForm. Without you just handover a link to the class.
in this view/template you do not yet have an instance of newgallery (just the form). So you can not use newgaller.id. Implement a POST branch in newgallery to save it and remove newgallery.id from the form action and point the action back to newgallery view.
after saving you have a newgallery instance with an id and you can call the edit view if you need to with newgallery in the context
def newgallery(request, username):
if request.method == 'POST':
# save newgallery here
if request.method == 'GET':
form = NewGalleryForm()
context = {
'form': form,
'username': username,
}
return render(request, 'galleries/newgallery.html', context)
<form action="{% url 'gallery_app:newgallery' user.username %} " style .... >
You need to pass the gallery as context into the view that has the edit form. I don't see in the views that you posted that you have a detail view but I do see a detail view url. So I'm assuming you're passing the edit form to your create view instead? That view doesn't return a context with new_gallery as a context variable. I would create a detail view for your gallery instead and pass the edit form, user and gallery as context to the template.
Reverse for 'editgallery' with arguments '('rodneyadmin', '')' not found.
New context
def galleryview(request, username, gallery_id):
# Logic
gallery = get_object_or_404(Gallery, pk=gallery_id)
context = {
'form': form,
'username': username,
'new_gallery': gallery,
}
# return an html response with context
Also, when you instantiate an unbound form you should add parenthesis after it.
form = NewGalleryForm()
I'm trying to do a block tr inside an HTML table using the Python Jinja library for Front-end. The table appears to me with the following appearance:
El código HTML es el siguiente:
<body>
<div id="testName">
{{ ca['name'] }}
</div>
<br>
<div id="testDates">
Start test Date: <span>{{ ca['start_ca'] | time_str }}</span>
<br>
End test Date: <span>{{ ca['end_ca'] | time_str }}</span>
</div>
{% for stage in ca['stages'] %}
<table class="blueTable">
<tbody style="page-break-inside: auto;" >
<tr id="rowOne">
<th style="font-weight:bolder;">Stage</th>
<th colspan="5">Start Date</th>
<th colspan="5">End Date</th>
</tr>
<tr id="rowTwo">
<td >{{ stage.name }}</td>
<td colspan="5">{{stage.start | time_str}}</td>
<td colspan="5">{{stage.end | time_str}}</td>
</tr>
<tr style="background-color: #1C6EA4; color: white;">
<th>Step ID</th>
<th>Step</th>
<th>Start Date</th>
<th>End Date</th>
<th>Expected</th>
<th>Found</th>
<th>Not Found</th>
<th>Expected Ok</th>
<th>Ok</th>
<th>Fails</th>
<th>Overall</th>
</tr>
{%for step in stage.steps%}
<tr id="filaBucle">
<th rowspan='{{ step[1] | size }}'>
{{step[0]}}
</th>
{%for s in step[1]%}
<th >{{s.name}}</th>
<td>{{s.start | time_str}}</td>
<td>{{s.end | time_str}}</td>
<td style="color:darkblue;">{{s.expected}}</td>
<td style="color:green;">{{s.found}}</td>
<td style="color:red;">{{s.not_found}}</td>
<td style="color:darkblue;">{{s.expected_ok}}</td>
<td style="color:green;">{{s.ok}}</td>
<td style="color:red;">{{s.fails}}</td>
{% if s.overall < 50 %}
<td style="color: red;">{{s.overall}}%</td>
{% elif 50 <= s.overall < 100 %}
<td colspan="1" style="color: brown;">{{s.overall}}%</td>
{% else %}
<td style="color: green;">{{s.overall}}%<br></td>
{% endif %}
{% endfor %}
</tr>
{% if step[1] | has_errors %}
<tr style="color: #F3E9EB;background-color: #8E8585; border-style: hidden;">
<th colspan="11"> Errors Details</th>
</tr>
{%for s in step[1]%}
{% if s.error_detail %}
<tr style="color: #D22020; background-color: #D3C9C9;">
<th colspan="2">Step ID: {{s._id}}</th>
<th colspan="9"> {{s.name}}</th>
</tr>
{% for detail in s.error_detail %}
<tr style="color: #D22020; background-color: #D3C9C9;">
<td colspan="11"> {{detail | replace("\n", "<br>")}}</td>
</tr>
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
</tbody>
</table>
{% endfor %}
I have tried to do everything possible with the CSS, but everything is out of place and I can't put those rows as subsections of the first column where it is numbered
I'm trying to create an if else condition using jinja2 where only table row with the status pending_approval or scheduled will display a delete button beside it. But I'm having trouble figuring it out because all the data in the table is displayed in a for loop so if the condition is true and all row have the delete button and vice versa.
Any help is much appreciated
Below is my code :
model.py
class Leave(models.Model):
employee = models.ForeignKey(Employee, on_delete=models.CASCADE, related_name='+')
type = models.ForeignKey(LeavesType, on_delete=models.CASCADE, related_name='+')
status = (('cancelled', 'Cancelled'),
('taken', 'Taken'),
('pending_approval', 'Pending Approval'),
('scheduled', 'Scheduled'),
('weekend', 'Week End'),
('public_holiday', 'Public holiday'),
)
status = models.CharField(max_length=50, choices=status, default='pending_approval')
view.py
def my_leaves_view(request):
leaves_log = Leave.objects.all().filter(employee=request.user.profile.employee.id)
context = {'leaves_log': leaves_log}
return render(request, 'hrm/employee/details/my_leaves.html', context)
html
<table id="Log" class="display table table-hover table-responsive leaves-table">
<thead>
<tr>
<th class="small text-muted text-uppercase"><strong>Leave Type</strong></th>
<th class="small text-muted text-uppercase"><strong>Status</strong></th>
<th class="small text-muted text-uppercase"><strong></strong></th>
</tr>
</thead>
<tbody>
{% for field in leaves_log %}
<tr>
<td>{{field.type}}</td>
<td><img class="media-object img-circle status-icon-size" src="/media/dashboard/ui/file_status/{{field.status}}.png" style="display: inline-block; height: 24px; margin-right: 10px;">{{field.status}}</td>
<td><div class="btn-group">
{% if field.status == 'pending_approval' or 'scheduled'%}
<button type="button" class="btn btn-default btn-xs dropdown-toggle active" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Action <span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li onclick="delete_leaves();">
<a href="/hrm/employee/{{field.id}}/delete/" onclick="return confirm('Are you sure you want to delete this item?');">
<i class="fa fa-fw fa-trash text-gray-lighter m-r-1"></i>Withdraw
</a>
</li>
</ul>
</div>
</td>
{% else %}
<td></td>
{% endif %}
</tr>
</tbody>
You are not using the or operator correctly. It is used to separate two boolean values, so you can imagine
{% if field.status == 'pending_approval' or 'scheduled' %}
being interpreted as
{% if bool(field.status == 'pending_approval') or bool('scheduled') %}
and bool('any non-empty string') is always True
The correct syntax is
{% if field.status == 'pending_approval' or field.status == 'scheduled' %}
or
{% if field.status in ['pending_approval', 'scheduled'] %}
The goal here is to show each bar corresponding to association and total members as displayed below:
What I get is this one big block with no value.
Seems that no one has the same issue here that I have been looking for.
Still a newbie so appreciate all your help & guidance, folks!
models.py
class Member(models.Model):
member_no = models.AutoField(primary_key=True)
association = models.ForeignKey('Association')
...
class Association(models.Model):
asoc_name = models.CharField(max_length=50, null=True, blank=True)
class Meta:
db_table = 'Association'
def __str__(self):
return self.asoc_name
def __unicode__(self):
return self.asoc_name
class AssociationSummary(Association):
class Meta:
proxy = True
verbose_name = 'Association Summary'
verbose_name_plural = 'Association Summary'
admin.py
#admin.register(AssociationSummary)
class ChartAssociationAdmin(admin.ModelAdmin):
change_list_template = 'admin/chart_association.html'
def changelist_view(self, request, extra_context=None):
response = super(ChartAssociationAdmin, self).changelist_view(
request,
extra_context=extra_context,
)
try:
qs = response.context_data['cl'].queryset
except (AttributeError, KeyError):
return response
metrics = {
'association': Count('asoc_name'),
'total': Sum('member'),
}
response.context_data['summary'] = list(
qs.values('asoc_name', 'member').annotate(**metrics)
)
response.context_data['summary_total'] = dict(
qs.aggregate(**metrics)
)
summary_over_time = qs.values('asoc_name', 'member').annotate(total=Sum('member'))
summary_range = summary_over_time.aggregate(
low=Min('total'),
high=Max('total'),
)
high = summary_range.get('high', 0)
low = summary_range.get('low', 0)
response.context_data['summary_over_time'] = [{
'asoc_name': x['asoc_name'],
'total': x['total'] or 0,
'pct':\
((x['total'] or 0) - low) / (high - low) * 100
if high > low else 0,
} for x in summary_over_time]
return response
chart_association.html
{% extends 'admin/change_list.html' %}
{% block content_title %}
<h1> Association Summary </h1>
{% endblock %}
{% block result_list %}
<div class=”results”>
<table>
<thead>
<tr>
<th>
<div class=”text”>
<span>Association</span>
</div>
</th>
<th>
<div class=”text”>
<span>Total Members</span>
</div>
</th>
</tr>
</thead>
<tbody>
{% for row in summary %}
<tr class="{% cycle 'row1' 'row2' %}">
<td> {{ row.asoc_name }} </td>
<td> {{ row.total }} </td>
</tr>
{% endfor %}
</tr>
<tr style="font-weight:bold; border-top:2px solid #DDDDDD;">
<td> Total </td>
<td> {{ summary_total.total }} </td>
</tr>
</tbody>
</table>
</div>
<br>
<h2> Association Chart </h2>
<style>
.bar-chart {
display: flex;
justify-content: space-around;
height: 160px;
padding-top: 60px;
overflow: hidden;
}
.bar-chart .bar {
flex: 100%;
align-self: flex-end;
margin-right: 2px;
position: relative;
background-color: #79aec8;
}
.bar-chart .bar:last-child {
margin: 0;
}
.bar-chart .bar:hover {
background-color: #417690;
}
.bar-chart .bar .bar-tooltip {
position: relative;
z-index: 999;
}
.bar-chart .bar .bar-tooltip {
position: absolute;
top: -60px;
left: 50%;
transform: translateX(-50%);
text-align: center;
font-weight: bold;
opacity: 0;
}
</style>
<div class="results">
<div class="bar-chart">
{% for x in summary_over_time %}
<div class="bar" style="height:{{x.pct}}%">
<div class="bar-tooltip">
{{ x.total | default:0 }}<br>
{{ x.asoc_name }}
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
{% block pagination %}{% endblock %}