Hi, sorry if it seems such simple but honestly the solution I find on google (or my implementation) is breaking my code :/
How can i limit the digits as 2 after decimal point. Even it's 2.99999999 I would like to display as 2.30.
TIA
Here my code for this page (working but displays lots of digits after decimal point):
#app.route("/")
#login_required
def index():
"""Show portfolio of stocks"""
# Update the latest price information for the existing stock
user_id = session["user_id"]
stock_list = db.execute("SELECT stock_id, stock_symbol, shares, unit_price, total_price FROM stocks WHERE owner_name == %s", session["user_id"])
# Iterate through dictionaries in the results (list of rows(dicts))
length = len(stock_list)
for i in range(length):
stock_id = stock_list[i]["stock_id"]
symbol = stock_list[i]["stock_symbol"]
amount = stock_list[i]["shares"]
price_dict = lookup(symbol)
price = price_dict["price"]
total = price * amount
# Update stocks table for the logged in user
db.execute("UPDATE stocks SET unit_price = ?, total_price = ? WHERE stock_id = ?", price, total, stock_id)
# Extract updated data and display in the template
rows = db.execute("SELECT stock_symbol, stock_name, shares, unit_price, total_price FROM stocks WHERE owner_name == %s", session["user_id"])
rows2 = db.execute("SELECT cash FROM users WHERE username == %s", session["user_id"])
assets_list = db.execute("SELECT total_price FROM stocks WHERE owner_name == %s", session["user_id"])
stock_assets = 0.00
cash_asset_list = db.execute("SELECT cash FROM users WHERE username == %s", session["user_id"])
cash_asset = cash_asset_list[0]["cash"]
for i in range(len(assets_list)):
stock_assets = stock_assets + assets_list[i]["total_price"]
net_assets = stock_assets + cash_asset
return render_template("index.html", rows=rows, rows2=rows2, net_assets=net_assets)
My HTML template for the page
{% extends "layout.html" %}
{% block title %}
Home
{% endblock %}
{% block main %}
<table class="table table-hover">
<tr class="table-info">
<th scope="col">Symbol</th>
<th scope="col">Company</th>
<th scope="col">Shares</th>
<th scope="col">Price</th>
<th scope="col">TOTAL</th>
</tr>
{% for row in rows %}
<tr class="table-light">
<td>{{ row.stock_symbol }}</td>
<td>{{ row.stock_name }}</td>
<td>{{ row.shares }}</td>
<td>{{ row.unit_price }}</td>
<td>{{ row.total_price }}</td>
</tr>
{% endfor %}
</table>
<table class="table table-hover">
<tr class="table-dark">
<th scope="col">Cash Balance</th>
<th scope="col">Total Assets</th>
</tr>
{% for row2 in rows2 %}
<tr class="table-light">
<td>{{ row2.cash }}</td>
<td>{{ net_assets }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
You can create a function:
def truncate(f):
return math.floor(f * 10 ** 2) / 10 ** 2
And it will return the value without rounding with 2 decimal places.
Then when you do total just set it to the function of the result.
In python you can use the function round to limit the decimal for number of places.
x = 1.4499999
you can use round(x, number of decimal places)
x = round(x, 2)
Final output will be
x = 1.50
Related
I have changed several times my code and the html file but I still can't solve it :( i really have no idea about what else should i doon getting the index function to work in finance cs50! This function should return in an html page a table with the details of my transactions... this is my app.py:
def index():
"""Show portfolio of stocks"""
id = session["user_id"]
stocks = db.execute(
"SELECT stock_name, SUM(shares), stock_symbol FROM transactions GROUP BY stock_name HAVING user_id = ?", id)
portfolio = [0]
for stock in stocks:
stock_name = stock["stock_name"]
stock_symbol = stock["stock_symbol"]
shares = stock["SUM(shares)"]
quote = lookup(stock_symbol)
current_price = quote["price"]
shares_value = current_price*shares
portfolio.append([stock_name, stock_symbol, shares, current_price, shares_value])
return render_template("index.html", portfolio = portfolio)
this is my "index.html"
{% extends "layout.html" %}
{% block title %}
Stocks
{% endblock %}
{% block main %}
<h2>Your portfolio</h2>
<table>
<thead>
<tr>
<th>Stock Name</th>
<th>Stock Symbol</th>
<th>Total Shares</th>
<th>Current Stock Price</th>
<th>Total Shares Value</th>
</tr>
</thead>
<tbody>
{% for stock in portfolio %}
<tr>
<td>{{ stock.stock_name }}</td>
<td>{{ stock.stock_symbol }}</td>
<td>{{ stock.shares }}</td>
<td>{{ stock.current_price }}</td>
<td>{{ stock.shares_value }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
I am stuck trying to get my flask input function to work. I am trying to complete the CS50 2020 finance problem. Documentation for the problem can be found here. The code block bellow is the error message I get in the console when I try to use the index function is run. The api key I am using is valid and when inserting the whole url for the get request I get the expected information. Code may be somewhat messy, I have not cleaned it up and optimized it yet, because I can't get it to work.
DEBUG: SELECT quantity FROM oStocks WHERE userID = 5 AND stock = 'AAPL'
DEBUG: Starting new HTTPS connection (1): cloud.iexapis.com:443
DEBUG: https://cloud.iexapis.com:443 "GET /stable/stock/GOOGL-AF/quote?token=<MY_API_KEY> HTTP/1.1" 200 None
I have tried all I could think of to try and fix this error. changed and unchanged nearly everything about the lookup function. I can't seem to find what is wrong. Can someone please point me in the right direction. Thank you
flask index:
#app.route("/")
#login_required
def index():
userid = session["user_id"]
owned = db.execute("SELECT stock FROM oStocks WHERE userID = :userid", userid=userid)
OwnedStocks = []
for row in owned:
OwnedStocks.append(row["stock"])
stockInfo = {}
for item in OwnedStocks:
itemInfo = lookup(item)
tmpQuantity = db.execute("SELECT quantity FROM oStocks WHERE userID = :userid AND stock = :stock", userid=userid, stock=item)
quantity = tmpQuantity[0]["quantity"]
sharePrice = itemInfo["price"]
name = itemInfo["name"]
value = quantity * sharePrice
stockInfo[item] = {}
stockInfo[item]['symbol'] = item
stockInfo[item]['name'] = name
stockInfo[item]['shares'] = quantity
stockInfo[item]['price'] = sharePrice
stockInfo[item]['value'] = value
return render_template("portfolio.html", stocks=stockInfo)
Lookup Function:
def lookup(symbol):
"""Look up quote for symbol."""
# Contact API
try:
api_key = os.environ.get("API_KEY")
response = requests.get(f"https://cloud.iexapis.com/stable/stock/{urllib.parse.quote_plus(symbol)}/quote?token={api_key}")
response.raise_for_status()
except requests.RequestException:
return None
# Parse response
try:
quote = response.json()
return {
"name": quote["companyName"],
"price": float(quote["latestPrice"]),
"symbol": quote["symbol"]
}
except (KeyError, TypeError, ValueError):
return None
Portfolio html:
{% extends "layout.html" %}
{% block title %}
Portfolio
{% endblock %}
{% block main %}
<div>
<table class="table table-hover">
<thead>
<tr class="font-weight-bold">
<th scope="col">Symbol</th>
<th scope="col">Name</th>
<th scope="col">Shares</th>
<th scope="col">Price</th>
<th scope="col">Total</th>
</tr>
</thead>
<tbody>
{% for stock in stocks %}
<tr>
<th scope="row">{{ stock['symbol'] }}</th>
<td>{{ stock['name'] }}</td>
<td>{{ stock['shares'] }}</td>
<td>{{ stock['price'] }}</td>
<td>{{ stock['total'] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
I have found the solution, now finding it I feel dumb having looked in all the wrong places so long. My mistake was in iterating and calling values from a dictionary passed into a flask template. After much search I ended up realizing and fixing my problem while going through camposha.
My original method was:
{% for stock in stocks %}
<tr>
<th scope="row">{{ stock['symbol'] }}</th>
<td>{{ stock['name'] }}</td>
<td>{{ stock['shares'] }}</td>
<td>{{ stock['price'] }}</td>
<td>{{ stock['total'] }}</td>
</tr>
{% endfor %}
However the proper way to achieve my goal was:
{% for stock, value in stocks.items() %}
<tr>
<th scope="row">{{ value['symbol']['stock'] }}</th>
<td>{{ value['name'] }}</td>
<td>{{ value['shares'] }}</td>
<td>{{ value['price'] }}</td>
<td>{{ value['value'] }}</td>
</tr>
{% endfor %}
I aslo made some adjustments to my index:
def index():
userid = session["user_id"]
owned = db.execute("SELECT stock, quantity FROM oStocks WHERE userID = :userid", userid=userid)
stockInfo = {}
for item in owned:
print(item)
itemInfo = lookup(item['stock'])
quantity = item['quantity']
name = itemInfo['name']
sharePrice = float(itemInfo['price'])
value = quantity * sharePrice
stockInfo[item['stock']] = {}
stockInfo[item['stock']]['symbol'] = item
stockInfo[item['stock']]['name'] = name
stockInfo[item['stock']]['shares'] = quantity
stockInfo[item['stock']]['price'] = sharePrice
stockInfo[item['stock']]['value'] = value
return render_template("portfolio.html", stocks=stockInfo)
I have been stuck on this problem set involving Flask, SQL, HTML regarding a finance website which should display a table of the user's portfolio on its homepage. More information regarding the problem set here.
I have been stuck on the homepage, as I manage to display a table, yet some table data does not appear. I have tried to understand why, and it does not seem that the "current share price" is the issue, as it calculates the total correctly at the bottom. I do not know where the issue arises from HTML or Flask, and if anyone could help me it would be greatly appreciated.
Here is my HTML code (index.html):
<table class="table table-striped" style="width:100%">
<h2> My Portfolio </h2>
<br>
<tr>
<th>Stocks Owned</th>
<th>Shares Owned</th>
<th>Current Price</th>
<th>Total Value</th>
</tr>
{% for stock in stocks %}
<tr>
<td>{{ stock.symbol }}</td>
<td>{{ stock.shares }}</td>
<td>{{ stocks.price }}</td>
<td>{{ stocks.total }}</td>
</tr>
{% endfor %}
<tr>
<td>CASH</td>
<td></td>
<td></td>
<td>{{ cash }}</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td><b>{{ grand_total }}</b></td>
</tr>
</table>
Here is my Flask Code:
#app.route("/")
#login_required
def index():
"""Show portfolio of stocks"""
stocks = db.execute("SELECT symbol, shares FROM transactions where user_id =:id", id = session["user_id"])
updated_cash = db.execute("SELECT cash FROM users WHERE id=:id", id=session["user_id"])
total_cash = float(updated_cash[0]['cash'])
grand_total = total_cash
for stock in stocks:
symbol = str(stock["symbol"])
shares = int(stock["shares"])
quote = lookup(symbol)
price = float(quote["price"])
total = float(shares * price)
grand_total = grand_total + total
return render_template("index.html", stocks=stocks, cash=total_cash, grand_total= grand_total)
Here is also a picture of the table which outcomes, and the missing fields (see hyperlink):
As you can see, the "Current Price" and "Total Value" fields are empty
Any help would be greatly appreciated, thanks a lot for any input thought!
Consider building a list of dictionaries that you can iterate in Jinja with period qualified names. Right now only stock and shares from query call are the only known elements of stocks. Specifically, replace for loop with list/dictionary comprehension:
def index():
"""Show portfolio of stocks"""
stocks = db.execute("SELECT symbol, shares FROM transactions where user_id =:id", id = session["user_id"])
updated_cash = db.execute("SELECT cash FROM users WHERE id=:id", id=session["user_id"])
total_cash = float(updated_cash[0]['cash'])
# BUILD LIST OF DICTIONARIES
data_list = [{'symbol': stock["symbol"],
'shares': stock["shares"],
'price': round(lookup(stock["symbol"])["price"], 2),
'total': round(stock["shares"] * lookup(stock["symbol"])["price"], 2)}
for stock in stocks]
# SUM ALL total ELEMENTS
grand_total = total_cash + sum(item['total'] for item in data_list)
return render_template("index.html", stocks=data_list,
cash=total_cash, grand_total=grand_total)
So what you're basically doing here is resetting your value every loop in the for stock in stocks loop. So every time you iterate over it, you're setting a new value for symbol, shares, quote, etc. What you want to do is append them to a list, and send that over.
I think something like this should work:
symbol = shares = quote = price = total = []
for stock in stocks:
symbol.append(str(stock["symbol"])
shares.append(int(stock["shares"])
....
Better yet would be to create a dictionary for each stock that holds the specific values, ensuring that all the relevant values stick together.
Something like this I guess
stocks = {
"AAPL": {
"shares": ,
"quote": ,
"price": ,
"total"
},
"TSLA": {
...
},
...
}
this is my code
sell1.html
{% for stock in stocks %}
<tr>
<th scope="row" name="stock">{{ stock[0] }}</th>
<td>{{ stock[1] }}</td>
<td>{{ stock[2] }}</td>
<td>{{ stock[3] }}</td>
<td>{{ stock[4] }}</td>
<td>Sell </td>
</tr>
{% endfor %}
app.py
#app.route("/sell/<string:stock>", methods=["GET", "POST"])
#login_required
def sell1(stock):
"""Sell shares of stock"""
# User reached route via POST (as by submitting a form via POST)
if request.method == "POST":
# collect relevant informations
amount = int(request.form.get("amount"))
symbol = request.form.get("symbol")
price = lookup(symbol)["price"]
value = round(price * float(amount))
# Update stocks table
amount_before = db.execute("SELECT amount FROM stocks WHERE user_id = :user AND symbol = :symbol",
symbol=symbol, user=session["user_id"])[0]['amount']
amount_after = amount_before - amount
# delete stock from table if we sold every unit we had
if amount_after == 0:
db.execute("DELETE FROM stocks WHERE user_id = :user AND symbol = :symbol",
symbol=symbol, user=session["user_id"])
# stop the transaction if the user does not have enough stocks
elif amount_after < 0:
return apology("That's more than the stocks you own")
# otherwise update with new value
else:
db.execute("UPDATE stocks SET amount = :amount WHERE user_id = :user AND symbol = :symbol",
symbol=symbol, user=session["user_id"], amount=amount_after)
# calculate and update user's cash
cash = db.execute("SELECT cash FROM users WHERE id = :user",
user=session["user_id"])[0]['cash']
cash_after = cash + price * float(amount)
db.execute("UPDATE users SET cash = :cash WHERE id = :user",
cash=cash_after, user=session["user_id"])
# Update history table
db.execute("INSERT INTO transactions(user_id, symbol, amount, value) VALUES (:user, :symbol, :amount, :value)",
user=session["user_id"], symbol=symbol, amount=-amount, value=value)
# Redirect user to home page with success message
flash("Sold!")
return redirect("/")
# User reached route via GET (as by clicking a link or via redirect)
else:
# Add Symbol
# query database with the transactions history
rows = db.execute("SELECT symbol, amount FROM stocks WHERE (user_id = :user AND symbol = :stock)",
user=session["user_id"], stock=stock)
stocks = {}
for row in rows:
stocks[row['symbol']] = row['amount']
return render_template("sell1.html", stocks=stocks)
and
in index.html:
{% for stock in stocks %}
<tr>
<th scope="row" name="stock">{{ stock[0] }}</th>
<td>{{ stock[1] }}</td>
<td>{{ stock[2] }}</td>
<td>{{ stock[3] }}</td>
<td>{{ stock[4] }}</td>
<td>Sell </td>
</tr>
index page works fine as it send this Get:
"GET /sell1/AAPL HTTP/1.1" 404 -
But after I have issue as it is a 404 page with this url:
http://127.0.0.1:5000/sell1/AAPL
I tried to check sql query and it works fine.
this is schema of stocks table:
'stocks' ('id' integer PRIMARY KEY AUTOINCREMENT NOT NULL, 'user_id' integer NOT NULL, 'symbol' char(4) NOT NULL, 'amount' integer NOT NULL);
thanks for help as I m new in flask and python...
thanks to mouse tail,
In my route, I forgot sell1
#app.route("/sell1/<string:stock>", methods=["GET", "POST"])
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}