How to render results from groupby query in html - Django - python

I'm trying to render results of a group by query from a view to an HTML table but it is returning nothing. I originally had success in listing all results, but after applying the sum aggregation I can't get it to appear.
Django View - with Group By
def get_asset_price(request):
# CryptoAssets is the model
obj = CryptoAssets.objects.filter(user_id=request.user.id).values('symbol')
obj = obj.annotate(total_units=Sum('units'),
total_cost=Sum('cost'))\
.order_by('symbol')
# Returns list of dictionaries
context = {
'object': obj
}
return render(request, 'coinprices/my-dashboard.html', context)
HTML
<style>
table, th, td {
border: 1px solid black;
}
</style>
<div class="container">
<h1>My Dashboard</h1>
<table>
<tr>
<th>Symbol</th>
<th>Total Units</th>
<th>Total Cost</th>
</tr>
{% for row in object %}
<tr>
<td>{{ row.symbol }}</td>
<td>{{ row.units }}</td>
<td>{{ row.cost }}</td>
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
I'll provide the view below that worked without the group by.
Django View - No group by
def get_asset_price(request):
# CryptoAssets is the model
obj = CryptoAssets.objects.all().filter(user_id=request.user.id)
# Returns list of objects
context = {
'object': obj
}
return render(request, 'coinprices/my-dashboard.html', context)

I think you're calling an attribute which does not exist on your object. The type of your object is a list of dictionaries. Change your template codes to something like this (this is the simplest way and maybe you can improve it later like adding a template tag similar to the one that is used in this question):
<table>
<tr>
<th>Symbol</th>
<th>Total Units</th>
<th>Total Cost</th>
</tr>
{% for row in object %}
<tr>
{% for key, value in row.items %}
<td>{{ key }}</td>
<td>{{ value }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>

Related

Django display list of dictionary in template - dict key is a 'variable'

I am using Django 4.0 to display a frontend page which source data is a list of dict.
I want to order the keys of the dict and then display all dict in the list in the same order.
Here is my views.py:
def UserGoalstatus(request, promise_token):
print("__UserGoalstatus__")
from cmd_utils import Retrieve_goal
data = Retrieve_goal(promise_token)
keys = set()
for item in data:
keys.update(set(item))
key_order = sorted(keys)
context = {
"data": data,
"key_order": key_order,
}
return render(request, 'json_table.html', context)
Here is the content of my 'data' variable:
[
{'goal_key': '286815', 'goal_type': 'hotelreservation', 'goal_id': 16149845, 'promise_token': '9ba51cbc-830b-64d603904099', 'campaign_id': 1002204, 'properties': {'price': 100, 'created': '2022-06-13 10:48:34', 'checkout': '2022-06-13', 'currency_code': 'USD', 'completed_booking_status': 1}},
{'goal_key': '1208107', 'goal_type': 'hotelreservation', 'goal_id': 16149846, 'promise_token': '9ba51cbc-830b-64d603904099', 'campaign_id': 1002204, 'properties': {'price': 100, 'created': '2022-06-13 10:48:35', 'checkout': '2022-06-13', 'currency_code': 'USD', 'completed_booking_status': 1}}
]
Here is my html file which I would like to print all content in data in the order of 'key_order'
<table id="dtBasicExample" class="table table-hover table-striped table-bordered" cellspacing="0" width="100%">
<thead>
<tr>
{% for key in key_order %}
<th>{{ key }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for item in data %}
<tr>
{% for key in key_order %}
<td>{{ item.get(key) }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
This part seems not right :{{ item.get(key) }} , anyone can suggest the right way to access the value mapping to the specific key ?
Here is my solution
I need to define a django template filter of my own
The key part is 'get_item' , it can parse dictionary key as 'variable' in Django html now .
For more detailed information refer to links below:
Django guide
stackoverflow answer
views.py
# customized template for html
from django.template.defaulttags import register
#register.filter
def get_item(dictionary, key):
return dictionary.get(key)
in json_table.html
<table id="dtBasicExample" class="table table-hover table-striped table-bordered" cellspacing="0" width="100%">
<thead>
<tr>
{% for key in key_order %}
<th>{{ key }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for item in data %}
<tr>
{% for key in key_order %}
<td>{{ item | get_item:key}}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>

Python / Django - How to map a list of values in a dictionary to a HTML table?

My Django View:
def hub(request):
context = {}
hub_id = [value['id'] for value in hub_data['data']]
hub_name = [value['attributes']['name'] for value in hub_data['data']]
hub_url = [value['links']['self']['href'] for value in hub_data['data']]
nested_dict = dict(zip(hub_name, map(list, zip(hub_id, hub_url))))
context ['rows'] = nested_dict
return render(request, 'connector/hub.html', context)
The context['rows'] results in:
{'rows': {hub_name1 : ['hub_id1', 'hub_url1'],{hub_name2 : ['hub_id2', 'hub_url2'], etc.. }
I am trying to pass it a HTML table that looks like this:
<th scope="col">Hub Name</th>
<th scope="col">Hub ID</th>
<th scope="col">Hub URL</th>
My tablebody looks like this:
<tbody>
{% for key, value in rows.items %}
<tr>
<td> {{ key }}</td>
<td> {{ value }}</td> **//how do i just get hub_id here**
<td> Don't know what to do here to get: hub_url </td>
</tr>
{% endfor %}
</tbody>
But I want to add another -tag to fill with hub_url. How do I extract the hub_id data and add it to the column: Hub ID and extract the hub_url and add it to the column Hub URL.
Any help would be much appreciated!
You can pass the data to the template without transforming it
return render(request, 'connector/hub.html', {'data': hub_data['data']})
And then lookup the attributes using the "dot" template syntax for each row
<tbody>
{% for row in data %}
<tr>
<td>{{ row.attributes.name }}</td>
<td>{{ row.id }}</td>
<td>{{ row.links.self.href }}</td>
</tr>
{% endfor %}
</tbody>

Django: retrieve table data in html page

I have a Django table with 3 fields.
I have a total of 4 entries and i want to visualize all of them inside a table which only displays 2 of these 3 fields.
How should i do that? i did manage to only display 1 row instead of 4, i'm struggling, someone could help?
This is the easy model to manage.
class Inc(models.Model):
id = models.AutoField(primary_key=True)
nr_sin = models.CharField(max_length=50, default=None)
nr_pol = models.CharField(max_length=50, default=None)
Have you already got the QuerySet being passed from your view to your templates?
Assuming you have, and it's in a variable called inc_list, then in your template you could do this to display the nr_sin and nr_pol fields:
{% if inc_list %}
<table>
<thead>
<tr>
<th>NR SIN</th>
<th>NR POL</th>
</tr>
</thead>
<tbody>
{% for inc in inc_list %}
<tr>
<td>{{ inc.nr_sin }}</td>
<td>{{ inc.nr_pol }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
In you view query your model to get all the entries you want to display in the table and pass them as a context variable to the templete. Later in the template you have to iterate over the list of elements and render one by one as follow:
# import your model
class SomeView(View):
def get(self, request):
elements = Inc.objects.all()
context = {'elements': elements}
return render(request, 'your_template.html', context)
render the table:
<table>
<thead>
<tr>
<th>ID</th>
<th>nr_sin</th>
</tr>
</thead>
<tbody>
{# you loop over the list and render one element at each iteration #}
{% for inc in elements %}
<tr>
<td>{{ inc.pk }}</td>
<td>{{ inc.nr_sin }}</td>
</tr>
{% endfor %}
</tbody>
</table>

Not able to send checkbox data from all pagination in datatable from template to view in django

I have a datatable in my django template in which there is a checkbox next to every row to send the row data to a view function to make some mass updations in django model. But problem is if the multiple rows are on the same page in pagination then i can send the data accurately BUT if i select row 2 from page 1 and row 5 from page 3 only the row value from page 3 will be sent to the view function.!
TEMPLATE.HTML
{% block jquery %}
<script type="text/javascript" class="init">
$(document).ready( function ($) {
var $submit = $("#updiv").hide(),
$cbs = $('input[name="updelegate"]').click(function() {
$submit.toggle( $cbs.is(":checked") );
});
$('#myTable').DataTable({
dom: 'lBfrtip',
"pageLength": 1,
"language": {
"emptyTable": "No Delegates Available",
"sSearch": "Search Delegates: ",
"info": " Showing _START_-_END_ out of Total _TOTAL_ Delegates",
}
});
});
</script>
{% endblock %}
<form id="myForm" action="{% url 'mass-delegates' %}" method="POST">
{% csrf_token %}
<table id="myTable" class="table table-striped table-bordered" style="width:100%">
<thead class="thead-dark">
<tr>
<th></th>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Phone</th>
<th scope="col">Company</th>
<th scope="col">Designation</th>
<th scope="col">Address</th>
<th scope="col">City</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{% for del in delegates %}
<tr>
<td>
<label class="container">
<input type="checkbox" id="updelegate" name="updelegate"
value="{{ del.id }}">
<span class="checkmark"></span>
</label>
</td>
<td>{{ del.id }}</td>
<td>{{ del.first_name }} {{ del.last_name }}</td>
<td>{{ del.email }}</td>
<td>{{ del.phone }}</td>
<td>{{ del.company }}</td>
<td>{{ del.designation }}</td>
<td>{{ del.address }}</td>
<td>{{ del.city }} ({{ del.pincode }})</td>
<td>
View
</td>
<td>
Edit
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div id="updiv">
<select name="eventid">
{% for ev in events %}
<option value="{{ ev.id }}">{{ ev.name }}</option>
{% endfor %}
</select>
<input type="submit" onclick="return confirm('Confirm Adding to Event?');" class="upbtn"
name="update" value="Add to Event"/>
</div>
</form>
VIEW.PY
def mass_delegates(request):
if request.method == 'POST':
toupdate = request.POST.getlist('updelegate')
eventid = request.POST.get('eventid')
array_length = len(toupdate)
for i in range(array_length):
if not EventDelegate.objects.filter(event_id=eventid, delegate_id=toupdate[i]).exists():
EventDelegate.objects.create(event_id=eventid, delegate_id=toupdate[i])
return event_det(request, eventid)
Instead of using the checkboxes, you can directly use the select attribute in the Datatables api. Check Select Rows in Datatables
Moreover, Since you want to select multiple rows at once, you might consider checking Multi Select rows in Datatables out
You can add the id in the 0th column, then
dataTable = $(.selector).Datatable()
dataTable.columns([0]).visible(false);
You can hide the column like that and then when you send your request, you still have your id

Building a html table in jinja form dict of list

I have a long dictionary of data which looks like this,
('Item', 8): Components_data(base_quantity=63.0, items_data={'830927': [1.0, 14.851799999999999], '831103': [0.37170000000000003, 0.6972720300000002]}, price_labor=374.21824212, total=389.76731415)}
The key is a tuple and my values are in a namedtuple, with 3 integers and 1 dictionary where keys are strings and values are integers.
I want to use those values to build an Html table dynamically using jinja:
the result I want need to look like this:
Where the rows of components, Qty and Price unit are generated automatically according to the values of items_data in Componnents_data field.
here is what I have tried so far with jinja :
<table class="table table-bordered">
<thead>
<tr>
<th>Level</th>
<th>Item</th>
<th>Component</th>
<th>Qty</th>
<th>Price Unit</th>
<th>Price Total</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{% for item, components_data in prices.items() %}
<tr>
<td rowspan="3">{{item[1]}}</td>
<td rowspan="3">{{item[0]}}</td>
</tr>
{% for sub_components, sub_comp_dat in components_data.items_data.items()%}
<td>{{sub_components}}</td>
<td>{{ sub_comp_dat[0] }}</td>
<td>{{ sub_comp_dat[1] }}</td>
<td>{{ components_data.price_labor }}</td>
<td>{{ components_data.total }}</td>
</tr>
{% endfor %} {% endfor %}
<tr>
<td colspan="3" id='total-label'>Total</td>
<td colspan="4" id='total-value' text-align='right'>july</td>
</tr>
</tbody>
</table>
And the results looks like this :
I have tried every tip I know but cannot get the expected results, Any Help is welcome.
Thanks
I do not know the jinja syntax, but you can easily achieve your purpose storing a boolean value to check if the total has been already written.
e.g.:
{% for item, components_data in prices.items() %}
<tr>
<td rowspan="3">{{item[1]}}</td>
<td rowspan="3">{{item[0]}}</td>
</tr>
//set the flag to false
isFirstTime = false
{% for sub_components, sub_comp_dat in components_data.items_data.items()%}
<td>{{sub_components}}</td>
<td>{{ sub_comp_dat[0] }}</td>
<td>{{ sub_comp_dat[1] }}</td>
//show the price only the first time
if( isFortTime)
{
isFistTime = true;
<td rowspan="3">{{ components_data.price_labor }}</td>
<td rowspan="3">{{ components_data.total }}</td>
}
</tr>
{% endfor %}
{% endfor %}
Again this is not the correct syntax but you can achieve this with no problem.
Documentation:
Assign a variable in the template
If Statement
Thanks again #Alessandro.Vegna answer for the intuition of using if else statement.
It can be achieved according to this answer by using namespaces: in jinja 2.0
here is the answer :
<tbody>
{% for item, components_data in prices.items() %}
<tr>
<td rowspan="3">{{item[1]}}</td>
<td rowspan="3">{{item[0]}}</td>
</tr>
{% set time = namespace(first=False) %}
{% for sub_components, sub_comp_dat in components_data.items_data.items() %}
<tr>
<td>{{sub_components}}</td>
<td>{{ sub_comp_dat[0] }}</td>
<td>{{ sub_comp_dat[1] }}</td>
{% if not time.first %}
{% set time.first = True %}
<td rowspan="3">{{ components_data.price_labor }}</td>
<td rowspan="3">{{ components_data.total }}</td>
{% endif %}
</tr>
{% endfor %} {% endfor %}
<tr>
<td colspan="3" id='total-label'>Total</td>
<td colspan="4" id='total-value' text-align='right'>july</td>
</tr>
</tbody>

Categories

Resources