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 %}
Related
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.
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 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 have a model defined as such in my models.py file:
class Tutor(models.Model):
FirstName = models.CharField(max_length=50)
LastName = models.CharField(max_length=50)
Email = models.EmailField(max_length=100)
PhoneNumber = models.CharField(max_length=10)
RequestedHours = models.DecimalField(max_digits=3, decimal_places=1)
def __str__(self):
return str(self.FirstName + " " + self.LastName)
I want to create a page that displays all of this information in a table that is easy to read quickly. I have managed to do so for the most part, but I have always found 10-digit phone numbers to be more difficult to read without separators. Currently, the display output looks like this:
And the code for the table looks like this:
<div class="table-background">
<table class="table table-striped table-bordered table-hover">
<thead>
<tr class="bg-info">
<th colspan="2">Tutor</th>
</tr>
</thead>
<tbody>
<tr>
<th>First Name</th>
<th>Last Name</th>
</tr>
<tr>
<td>{{ tutor.FirstName }}</td>
<td>{{ tutor.LastName }}</td>
</tr>
<tr>
<th>Email</th>
<th> Phone Number</th>
</tr>
<tr>
<td>{{ tutor.Email }}</td>
<td>{{ tutor.PhoneNumber }}</td>
</tr>
<tr>
<th colspan="2">Requested Hours</th>
</tr>
<tr>
<td colspan="2">{{ tutor.RequestedHours }}</td>
</tr>
</tbody>
</table>
Is there any way for me to modify the output of the CharField PhoneNumber so that I can get it to display as 000-000-0000?
You should really format it in your view, but on the template side:
{% with pn=tutor.PhoneNumber|to_list %}
{{ pn|slice:":3"|join:'' }}-{{ pn|slice:"3:6"|join:'' }}-{{ pn|slice:"6:"|join:''}}
{% endwith %}
Your could also modify your model:
class Tutor(models.Model):
FirstName = models.CharField(max_length=50)
LastName = models.CharField(max_length=50)
Email = models.EmailField(max_length=100)
PhoneNumber = models.CharField(max_length=10)
RequestedHours = models.DecimalField(max_digits=3, decimal_places=1)
def __str__(self):
return str(self.FirstName + " " + self.LastName)
def get_formatted_phone(self):
return '{}-{}-{}'.format(self.PhoneNumber[:3],
self.PhoneNumber[3:6],self.PhoneNumber[6:])
Then in your template:
{{ tutor.get_formatted_phone }}
But this sort of stuff really belongs in the view.
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}