so I'm trying to make two lists in one view but with different filters. They also change whether the campaign is paused or is running. This is what I came up with but it throws this error: TypeError: init() got an unexpected keyword argument 'queryset_paused'
This is my views.py
def home_view(request):
#campaigns in progress
queryset = Campaign.objects.filter(is_active=True, completion_percent__lt=100)
if request.method == "POST":
form_type = request.POST.get('id')
if form_type == 'campaign_status':
formset = CampaignStatusFormSet(
request.POST, request.FILES,
queryset=queryset,
)
formset.save()
else:
formset = CampaignStatusFormSet(queryset=queryset)
campaigns_and_forms = list(zip(queryset, formset))
#paused campaigns
queryset_paused = Campaign.objects.filter(is_active=False, completion_percent__lt=100)
if request.method == "POST":
form_type = request.POST.get('id_paused')
if form_type == 'campaign_status_paused':
formset_paused = CampaignStatusFormSet(
request.POST, request.FILES,
queryset_paused=queryset_paused,
)
formset_paused.save()
else:
formset_paused = CampaignStatusFormSet(queryset_paused=queryset_paused)
campaigns_and_forms_paused = list(zip(queryset_paused, formset_paused))
context = {
'formset': formset,
'campaigns_and_forms': campaigns_and_forms,
'formset_paused': formset_paused,
'campaigns_and_forms_paused': campaigns_and_forms_paused,
}
return render(request, 'campaigns_in_progress.html', context)
Here is my template for the two lists
<table class="table table-striped table-hover table-bright table-bordered align-middle">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Nazwa</th>
<th scope="col">Temat</th>
<th scope="col">Nadawca</th>
<th scope="col">Procent Realizacji</th>
<th scope="col">Start Kampani</th>
<th scope="col">Stan</th>
</tr>
</thead>
<tbody>
<form method="post" id="campaign_status"> {% csrf_token %}
<input type='hidden' value='campaign_status' name='id'>
{{ formset.management_form }}
{% for campaign, form in campaigns_and_forms %}
<tr>
<td>{{ campaign.campaign_id }}</td>
<td>{{ campaign.name }}</td>
<td>{{ campaign.topic }}</td>
<td>{{ campaign.sender }}</td>
<td>
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: {{campaign.completion_percent}}%;" aria-valuenow="{{campaign.completion_percent}}" aria-valuemin="0" aria-valuemax="100">{{campaign.completion_percent}}%</div>
</div>
</td>
<td>{{ campaign.start_date }}</td>
<td>{{ form.as_p }}</td>
</tr>
{% endfor %}
</form>
</tbody>
</table>
<h4>Kampanie wstrzymane</h4>
<table class="table table-striped table-hover table-bright table-bordered align-middle">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Nazwa</th>
<th scope="col">Temat</th>
<th scope="col">Nadawca</th>
<th scope="col">Procent Realizacji</th>
<th scope="col">Start Kampani</th>
<th scope="col">Stan</th>
</tr>
</thead>
<tbody>
<form method="post" id="campaign_status_paused"> {% csrf_token %}
<input type='hidden' value='campaign_status_paused' name='id_paused'>
{{ formset_paused.management_form }}
{% for campaign, form in campaigns_and_forms_paused %}
<tr>
<td>{{ campaign.campaign_id }}</td>
<td>{{ campaign.name }}</td>
<td>{{ campaign.topic }}</td>
<td>{{ campaign.sender }}</td>
<td>
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: {{campaign.completion_percent}}%;" aria-valuenow="{{campaign.completion_percent}}" aria-valuemin="0" aria-valuemax="100">{{campaign.completion_percent}}%</div>
</div>
</td>
<td>{{ campaign.start_date }}</td>
<td>{{ form.as_p }}</td>
</tr>
{% endfor %}
</form>
</tbody>
</table>
Please tell me what am I doing wrong.
Related
I want to have 2 separate query lists on the same page but with different filters. First list must be played and the second one paused. This is what I came up with in my views.py file but it throws an error like this: UnboundLocalError at /
local variable 'formset_paused' referenced before assignment
def home_view(request):
#campaigns in progress
queryset = Campaign.objects.filter(is_active=True, completion_percent__lt=100)
if request.method == "POST":
form_type = request.POST.get('id')
if form_type == 'campaign_status':
formset = CampaignStatusFormSet(
request.POST, request.FILES,
queryset=queryset,
)
formset.save()
else:
formset = CampaignStatusFormSet(queryset=queryset)
campaigns_and_forms = list(zip(queryset, formset))
#paused campaigns
queryset_paused = Campaign.objects.filter(is_active=False, completion_percent__lt=100)
if request.method == "POST":
form_type_paused = request.POST.get('id_paused')
if form_type_paused == 'campaign_status_paused':
formset_paused = CampaignStatusFormSet(
request.POST, request.FILES,
queryset=queryset_paused,
)
formset_paused.save()
else:
formset_paused = CampaignStatusFormSet(queryset=queryset_paused)
paused_campaigns_and_forms = list(zip(queryset_paused, formset_paused))
context = {
'formset': formset,
'formset_paused': formset_paused,
'campaigns_and_forms': campaigns_and_forms,
'paused_campaigns_and_forms': paused_campaigns_and_forms,
}
return render(request, 'campaigns_in_progress.html', context)
Here are the tables in my template where I make those 2 lists.
<table class="table table-striped table-hover table-bright table-bordered align-middle">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Nazwa</th>
<th scope="col">Temat</th>
<th scope="col">Nadawca</th>
<th scope="col">Procent Realizacji</th>
<th scope="col">Start Kampani</th>
<th scope="col">Stan</th>
</tr>
</thead>
<tbody>
<form method="post" id="campaign_status"> {% csrf_token %}
<input type='hidden' value='campaign_status' name='id'>
{{ formset.management_form }}
{% for campaign, form in campaigns_and_forms %}
<tr>
<td>{{ campaign.campaign_id }}</td>
<td>{{ campaign.name }}</td>
<td>{{ campaign.topic }}</td>
<td>{{ campaign.sender }}</td>
<td>
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: {{campaign.completion_percent}}%;" aria-valuenow="{{campaign.completion_percent}}" aria-valuemin="0" aria-valuemax="100">{{campaign.completion_percent}}%</div>
</div>
</td>
<td>{{ campaign.start_date }}</td>
<td>{{ form.as_p }}</td>
</tr>
{% endfor %}
</form>
</tbody>
</table>
<h4>Kampanie zatrzymane</h4>
<table class="table table-striped table-hover table-bright table-bordered align-middle">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Nazwa</th>
<th scope="col">Temat</th>
<th scope="col">Nadawca</th>
<th scope="col">Procent Realizacji</th>
<th scope="col">Start Kampani</th>
<th scope="col">Stan</th>
</tr>
</thead>
<tbody>
<form method="post" id="campaign_status_paused"> {% csrf_token %}
<input type='hidden' value='campaign_status_paused' name='id_paused'>
{{ formset_paused.management_form }}
{% for campaign, form in paused_campaigns_and_forms %}
<tr>
<td>{{ campaign.campaign_id }}</td>
<td>{{ campaign.name }}</td>
<td>{{ campaign.topic }}</td>
<td>{{ campaign.sender }}</td>
<td>
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: {{campaign.completion_percent}}%;" aria-valuenow="{{campaign.completion_percent}}" aria-valuemin="0" aria-valuemax="100">{{campaign.completion_percent}}%</div>
</div>
</td>
<td>{{ campaign.start_date }}</td>
<td>{{ form.as_p }}</td>
</tr>
{% endfor %}
</form>
</tbody>
</table>
Before adding the second query and the second table everything worked.
So basically what I want is when the is_active filter is equal to True the campaign should be in the first list. If it's False then it should jump to the other. Can anyone help me?
If request.method == "POST" but form_type_paused != 'campaign_status_paused', the formset_paused variable is never assigned. But you try to access it here:
...
paused_campaigns_and_forms = list(zip(queryset_paused, formset_paused))
...
That is where the error comes from.
I'm trying to group articles in each day, image blow will show you how it looks like now
I have 3 records that have their date on top right of them, but as you can see each one of them is separated, I want to show record on this date in one group and tomorrow if I added more records shows on that date group,
my codes:
Models.py:
class Form(models.Model):
food_type = models.ForeignKey(FoodTypes, blank=False, null=True, on_delete=CASCADE)
calorie = models.CharField(max_length=50)
protein = models.ForeignKey(Protein, blank=False, null=True, on_delete=CASCADE)
carbohydrate = models.ForeignKey(Carbohydrate, blank=False, null=True, on_delete=CASCADE)
drinks = models.ForeignKey(Drinks, blank=False, null=True, on_delete=CASCADE)
fruits = models.CharField(max_length=50)
note = models.CharField(max_length=200, blank=True)
date = models.DateField(default=datetime.date.today)
views.py:
def requests(request):
lists = Form.objects.all().order_by('-date')
context = {
'lists': lists
}
return render(request, 'form/requests_list.html', context)
template file:
{% for lists in lists %}
<div class="req-list">
<h6>{{ lists.date }}</h6>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">نوع غذا</th>
<th scope="col">کالری</th>
<th scope="col">پروتئین</th>
<th scope="col">کربوهیدرات</th>
<th scope="col">نوشیدنی</th>
<th scope="col">میوه</th>
<th scope="col">توضیحات</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">{{ lists.id }}</th>
<td>{{ lists.food_type }}</td>
<td>{{ lists.calorie }}</td>
<td>#{{ lists.protein }}</td>
<td>#{{ lists.carbohydrate }}</td>
<td>#{{ lists.drinks }}</td>
<td>#{{ lists.fruits }}</td>
<td>#{{ lists.note }}</td>
</tr>
</tbody>
</table>
</div>
{% endfor %}
You can try using the {% ifchanged %} tag as mentioned in this answer: https://stackoverflow.com/a/3986324/4151233
Following code is not tested:
{% for lists in lists %}
{% ifchanged lists.date %}
<div class="req-list">
<h6>{{ lists.date }}</h6>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">نوع غذا</th>
<th scope="col">کالری</th>
<th scope="col">پروتئین</th>
<th scope="col">کربوهیدرات</th>
<th scope="col">نوشیدنی</th>
<th scope="col">میوه</th>
<th scope="col">توضیحات</th>
</tr>
</thead>
<tbody>
{% endifchanged %}
<tr>
<th scope="row">{{ lists.id }}</th>
<td>{{ lists.food_type }}</td>
<td>{{ lists.calorie }}</td>
<td>#{{ lists.protein }}</td>
<td>#{{ lists.carbohydrate }}</td>
<td>#{{ lists.drinks }}</td>
<td>#{{ lists.fruits }}</td>
<td>#{{ lists.note }}</td>
</tr>
{% ifchanged lists.date %}
</tbody>
</table>
</div>
{% endifchanged %}
{% endfor %}
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
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>
I am trying to show the total weight of assets I have presented on a table.
Each Asset has a weight and a quantity and I can present the total weight of each asset as below:
def by_item_weight(self):
"""This Method gives the total value of the asset. Weight * Qnty"""
total = self.asset_quantity * self.asset_weight
return total
What I would like to do is take the total item weight of each asset (result of qnty * weight) and present the over all weight of all assets.
I have tried to make various combinations of the below to return the sum of the by_item_weight 'column':
Asset.objects.all().annotate(total=Sum('by_item_weight')
But I understand this will not work as by-item-weight is not defined in the model Asset.
I am presenting the table via a for loop as below on my assetslist.html template:
{% block content %}
<table class="well table table-striped text-center">
<thead>
<tr class="text-center">
<th class="text-center">Asset ID:</th>
<th class="text-center">Asset Name:</th>
<th class="text-center">Asset Quantity:</th>
<th class="text-center">Asset Weight / kg:</th>
<th class="text-center">Total Weight / kg:</th>
<th class="text-center">Asset Owner:</th>
</tr>
</thead>
<tbody>
<tr class="text-center">
{% for asset in object_list %}
<td>{{ asset.id }}</td>
<td>{{ asset.asset_name }}</td>
<td>{{ asset.asset_quantity }}</td>
<td>{{ asset.asset_weight }}</td>
<td>{{ asset.by_item_weight }}</td>
<td>{{ asset.asset_owner }}</td>
</tr>
{% endfor %}
I am new to Python and am having trouble finding a way to capture the value of each asset.by_item_weight which If I could capture in a list I presume I could them sum the list and show the result.
My Models
class Asset(models.Model):
asset_name = models.CharField(max_length=30)
asset_quantity = models.IntegerField(default=0)
asset_weight = models.IntegerField(default=0)
asset_owner = models.ForeignKey(
'AssetOwner',
on_delete=models.CASCADE,
) # This should be a Foreign Key Drop down of AssetOwners owner_name.
def by_item_weight(self):
"""This Method gives the total value of the asset. Weight * Qnty"""
total = self.asset_quantity * self.asset_weight
return total
def __str__(self):
return '{}'.format(self.asset_name)
return 'Asset Quantity: {}'.format(self.asset_quantity)
return 'Asset Weight: {}'.format(self.asset_weight)
return 'Asset Owner: {}'.format(self.asset_owner)
return 'Asset Owner: {}'.format(self.asset_owner)
Any help would be much appreciated.
UPDATED:
No Errors now, but still not able to show/display the value of sum_total
New Template
{% extends "personal/header.html" %}
{% block content %}
<h1 class='text-center'>This is the full asset list not split by owner</h1></br>
<table class="well table table-striped text-center">
<thead>
<tr class="text-center">
<th class="text-center">Asset ID:</th>
<th class="text-center">Asset Name:</th>
<th class="text-center">Asset Quantity:</th>
<th class="text-center">Asset Weight / kg:</th>
<th class="text-center">Total Weight / kg:</th>
<th class="text-center">Asset Owner:</th>
</tr>
</thead>
<tbody>
<tr class="text-center">
{% for asset in object_list %}
<td>{{ asset.id }}</td>
<td>{{ asset.asset_name }}</td>
<td>{{ asset.asset_quantity }}</td>
<td>{{ asset.asset_weight }}</td>
<td>{{ asset.by_item_weight }}</td>
<td>{{ asset.asset_owner }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<p class="" style="">Total Weight In Stock : {{ asset.sum_total }}</p>
<p class="text-center">{% include "sam/includes/backtosam.html" %}</p>
{% endblock %}
New Models
from __future__ import unicode_literals
from django.db import models
from django.db.models import Sum, F, Count
from django.db.models import Max
from django.db.models import ExpressionWrapper
from django.db.models import Aggregate
class Asset(models.Model):
asset_name = models.CharField(max_length=30)
asset_quantity = models.IntegerField(default=0)
asset_weight = models.IntegerField(default=0)
asset_owner = models.ForeignKey(
'AssetOwner',
on_delete=models.CASCADE,
) # This should be a Foreign Key Drop down of AssetOwners owner_name.
def by_item_weight(self):
"""This Method gives the total value of the asset. Weight * Qnty"""
total = self.asset_quantity * self.asset_weight
return total
def sum_total(self):
assets = Asset.objects.all().annotate(
total_weight=ExpressionWrapper(F('asset_quantity') * F('asset_weight'),output_field=IntegerField))
the_sum = assets.aggregate(total=Sum('total_weight'))
return the_sum
def __str__(self):
return '{}'.format(self.asset_name)
return 'Asset Quantity: {}'.format(self.asset_quantity)
return 'Asset Weight: {}'.format(self.asset_weight)
return 'Asset Owner: {}'.format(self.asset_owner)
return 'Asset Owner: {}'.format(self.asset_owner)
return 'Total Weight of Assets: {}'.format(self.assets)
Updated view
from django.shortcuts import render
from django.http import HttpResponse
from django.core.cache import cache
from django.db.models import Sum, F
def get_total_weight(self):
total_weight = cache.get('total_weight',-1)
if total_weight == -1:
total_weight = Asset.objects.annotate(total_weight=F('asset_quantity')*F('asset_weight')).aggregate(total=Sum('total_weight'))
# this is tested
cache.set('total_weight',total_weight)
return total_weight
def index(request):
return render(request, 'sam/index.html')
def assetslist(request):
return render(request,'sam/assetslist.html',{'total_weight': get_total_weight}, assets = Asset.objects.all())
I suspect there is an issue with the above assetslist method which I am not apparently calling.
Template
{% extends "personal/header.html" %}
{% block content %}
<h1 class='text-center'>This is the full asset list not split by owner</h1></br>
<table class="well table table-striped text-center">
<thead>
<tr class="text-center">
<th class="text-center">Asset ID:</th>
<th class="text-center">Asset Name:</th>
<th class="text-center">Asset Quantity:</th>
<th class="text-center">Asset Weight / kg:</th>
<th class="text-center">Total Weight / kg:</th>
<th class="text-center">Asset Owner:</th>
</tr>
</thead>
<tbody>
<tr class="text-center">
{% for asset in object_list %}
<td>{{ asset.id }}</td>
<td>{{ asset.asset_name }}</td>
<td>{{ asset.asset_quantity }}</td>
<td>{{ asset.asset_weight }}</td>
<td>{{ asset.by_item_weight }}</td>
<td>{{ asset.asset_owner }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<p class="" style="">Total Weight In Stock : {{ get_total_weight }}</p>
<p class="" style="">Total Weight In Stock : {{ assetslist }}</p>
<!-- <table class="well table table-striped text-center">
<thead>
<tr class="text-center">
<th class="text-center"></th>
<th class="text-center"></th>
<th class="text-center"></th>
<th class="text-center"></th>
<th class="text-center">Total Weight / kg:</th>
</tr>
</thead>
<tbody>
<tr class="text-center">
{% for sum_weight in object_list %}
<td></td>
<td></td>
<td></td>
<td></td>
<td>{{ asset.sum_total }}</td>
</tr>
{% endfor %}
</tbody>
</table> -->
<p class="text-center">{% include "sam/includes/backtosam.html" %}</p>
{% endblock %}
Thanks for any input/suggestions.
Further UPDATE:
I have adjusted the view to the below:
from django.core.cache import cache
from django.db.models import Sum, F
def get_total_weight(self):
total_weight = cache.get('total_weight',-1)
if total_weight == -1:
total_weight = Asset.objects.annotate(total_weight=F('asset_quantity')*F('asset_weight')).aggregate(total=Sum('total_weight'))
# this is tested
cache.set('total_weight',total_weight)
return total_weight
render(request,'template_name',{'total_weight': get_total_weight, assets = Asset.objects.all() } )
I am getting errors on the assets = Asset.objects.all() } ) = sign. SyntaxError: invalid syntax
I presume that render needs to be in its own function?
UPDATE:
I have updated my views and moved the def from the models.py
my views.py file is as below
def total_weight(request):
assets = Asset.objects.all().annotate(
total_weight=ExpressionWrapper(F('asset_quantity') * F('asset_weight'),
output_field=IntegerField() ))
return render(request, 'sam/index.html')
def sum_total(request):
the_total = assets.aggregate(total=Sum('total_weight'))
return render(request, 'sam/assetlist.html')
def index(request):
return render(request, 'sam/index.html')
def by_item_weight(self):
"""This Method gives the total value of the asset. Weight * Qnty"""
total = self.asset_quantity * self.asset_weight
return total
def get_total_weight(self):
total_weight = Asset.objects.filter(by_item_weight__isnull=True).aggregate(Sum('by_item_weight'))
Asset.objects.annotate(total_weight=F('asset_quantity')*F('asset_weight')).aggregate(total=Sum('total_weight'))
def __str__(self):
return '{}'.format(self.asset_name)
return '{}'.format(self.total_weight)
assetlist.html
There is JS below that I tried to implement to resolve this issue which did not work either.
I feel like I am missing something on the assetlist.html in calling the values of the def in the views.py.
{% extends "personal/header.html" %}
{% block content %}
<h1 class='text-center'>This is the full asset list not split by owner</h1></br>
<table id="sum_table" class="well table table-striped text-center">
<thead>
<tr class="text-center titlerow">
<td class="text-center">Asset ID:</td>
<td class="text-center">Asset Name:</td>
<td class="text-center">Asset Quantity:</td>
<td class="text-center">Asset Weight / kg:</td>
<td class="text-center">Total Weight / kg:</td>
<td class="text-center">Asset Owner:</td>
</tr>
</thead>
<tbody>
<tr class="text-center">
{% for asset in object_list %}
<td><a href="/sam/assets/{{ asset.id }}">{{ asset.id }}</></td>
<td>{{ asset.asset_name }}</td>
<td>{{ asset.asset_quantity }}</td>
<td>{{ asset.asset_weight }}</td>
<td class="rowDataSd">{{ asset.by_item_weight }}</td>
<td><a href="/sam/owners/">{{ asset.asset_owner }}</></td>
</tr>
{% endfor %}
<tr class="totalColumn">
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class="totalCol">Total: {{ asset.get_total_weight }}</td>
<td class=""></td>
</tr>
</tbody>
</table>
<p>Hope this is full ( {{ this_view }} )?</p>
<p class="text-center">{% include "sam/includes/backtosam.html" %}</p>
<!--
<script>
var total = 0;
$('#sum_table tr td.rowDataSd').each(function() {
total += parseInt($(this).text());
});
$('#sum_table td.totalCol').text("total: " + total);
</script>
-->
{% endblock %}
UPDATE - 3rd July 2016
from __future__ import unicode_literals
from django.db import models
from django.db.models import Sum, F, Count
from django.db.models import Max
from django.db.models import ExpressionWrapper
from django.db.models import Aggregate
from django.contrib.auth.models import User
class Asset(models.Model):
asset_name = models.CharField(max_length=30)
asset_quantity = models.IntegerField(default=0)
asset_weight = models.IntegerField(default=0)
total_assets_weight = models.IntegerField(default=0)
asset_owner = models.ForeignKey(
'AssetOwner',
on_delete=models.CASCADE,
) # This should be a Foreign Key Drop down of AssetOwners owner_name.
def by_item_weight(self):
"""This Method gives the total value of the asset. Weight * Qnty"""
total = self.asset_quantity * self.asset_weight
return total
def total_weight(self):
assets = Asset.objects.all().annotate(
total_weight=ExpressionWrapper(F('asset_quantity') * F('asset_weight'),
output_field=IntegerField()))
the_total = assets.aggregate(total=Sum('total_weight'))
return the_total
template
{% extends "personal/header.html" %}
{% block content %}
<h1 class='text-center'>This is the full asset list not split by owner</h1></br>
<table id="sum_table" class="well table table-striped text-center">
<thead>
<tr class="text-center titlerow">
<td class="text-center">Asset ID:</td>
<td class="text-center">Asset Name:</td>
<td class="text-center">Asset Quantity:</td>
<td class="text-center">Asset Weight / kg:</td>
<td class="text-center">Total Weight / kg:</td>
<td class="text-center">Asset Owner:</td>
</tr>
</thead>
<tbody>
<tr class="text-center">
{% for asset in object_list %}
<td><a href="/sam/assets/{{ asset.id }}">{{ asset.id }}</td>
<td>{{ asset.asset_name }}</td>
<td>{{ asset.asset_quantity }}</td>
<td>{{ asset.asset_weight }}</td>
<td class="rowDataSd">{{ asset.by_item_weight}}</td>
<td><a href="/sam/owners/">{{ asset.asset_owner }}</td>
</tr>
{% endfor %}
{% for total in object_list %}
<tr class="totalColumn">
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class=""></td>
<td class="totalCol">Total: {{ total.total_weight }}</td>
<td class=""></td>
</tr>
</tbody>
</table>
{% endfor %}
<p class="text-center">{% include "sam/includes/backtosam.html" %}</p>
{% endblock %}
You could use the ExpressionWrapper() (mostly Django 1.8+)
assets = Asset.objects.all().annotate(
total_weight=ExpressionWrapper(F('asset_quantity') * F('asset_weight'),
output_field=IntegerField() ))
That should give you the total weight for each object, i.e. quantity times weight.
Now, you should be able to get a sum from all the total_weights.
Edit: Now you can use Aggregate to get the total
assets.aggregate(total=Sum('total_weight'))
{'total': 1234.5678}