CS50 Finance - index not displaying Portfolio correctly - python

I am having trouble getting the code to properly display the portfolio in index.html.
My logic with this function is to get a list of all the stocks and cash one user has, and then in a "for" loop, look up the company name and current price for each stock, the total value, and then insert all of that information into a new list of dictionaries (display_portfolio). Then the render_template should display "display_portfolio" with this information, as well as the user's total cash and total value of everything. However, with my current setup, it is displaying the total cash and grand total, but nothing from the individual stocks. I am really not sure why that is, and I am unsure if the issue is in my html or in the flask function itself.
This is the function:
#app.route("/")
#login_required
def index():
"""Show portfolio of stocks"""
# Retrive portfolio
portfolio = db.execute("SELECT symbol, SUM(amount) as amount FROM purchases WHERE id = ? ORDER BY symbol", (session["user_id"]))
user_cash = db.execute("SELECT cash FROM users WHERE id = ?", session["user_id"])
cash = user_cash[0]["cash"]
display_portfolio = []
shares_total = 0
# loop through portfolio symbols to access name and share price for each symbol
for row in portfolio:
requested_quote = lookup(row["symbol"])
symbol = row["symbol"]
amount = row["amount"] #shares
price = float(requested_quote["price"])
name = requested_quote["name"]
share_total = (float(amount) * price)
shares_total = shares_total + share_total
display_portfolio.append({'symbol':symbol, 'name':name, 'shares':amount, 'price':price, 'share_total':share_total})
grand_total = shares_total + cash
return render_template("index.html", display_portfolio = display_portfolio, cash = cash, grand_total = grand_total)
This is index.html:
{% extends "layout.html" %}
{% block title %}
Portfolio
{% endblock %}
{% block main %}
<div>
<table class="table table-striped">
<thead>
<tr>
<th>Symbol</th>
<th>Name</th>
<th>Shares</th>
<th>Price</th>
<th>TOTAL</th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="3"></td>
<td>TOTAL</td>
<td>{{ grand_total | usd }}</td>
</tr>
</tfoot>
<tbody>
{% for row in display_portfolio %}
<tr>
<td>{{ display_portfolio.symbol }}</td>
<td>{{ display_portfolio.name }}</td>
<td>{{ display_portfolio.shares }}</td>
<td>{{ display_portfolio.price }}</td>
<td>{{ display_portfolio.total }}</td>
</tr>
{% endfor %}
<td colspan="3"></td>
<td>Cash</td>
<td>{{ cash | usd }}</td>
</tbody>
</table>
</div>
{% endblock %}
I should also note, that when I add "| usd" to "display_portfolio.price" in that it reads:
<td>{{ display_portfolio.price | usd }}</td>
I am also getting a completely separate error, and not sure why it would work with cash and not this.
I can confirm that there exists purchases in the sql database the "portfolio" variable is retrieving.
This is what it looks like:
Display
Any help will be appreciated, thanks!

From MDN doc on tfoot:
Permitted parents: A <table> element. The <tfoot> must appear after
any <caption>, <colgroup>, <thead>, <tbody>, or <tr> element. Note
that this is the requirement as of HTML5.
Suspect the Cash line is displayed because it is missing <tr> tags.
Nu HTML Validator from W3C is your friend :)

Related

CS50 finance (Index) sqlite error near WHERE

This function is supposed to return a table that resumes all the transactions made grouping them by stock symbol. I'm stuck on this because I keep geting an error that seems to come from sqlite researche (transactions_sql) and more specially from the way I'm calling the user's id. Does someone can explain me what I'm doing wrong ? Did I not create the right link with the foreign key (id) on my transactions database ?
Here is the error message I get : RuntimeError: near "WHERE": syntax error
#app.route("/")
#login_required
def index():
"""Show portfolio of stocks"""
transactions_sql = db.execute("SELECT company_symbol, SUM(shares) FROM transactions GROUP BY company_symbol WHERE id IN (?)", session["user_id"])
index = lookup(transactions_sql.company_symbol)
value = index["price"] * int(transactions_sql.SUM(shares))
cash_sql = db.execute("SELECT cash FROM users WHERE id IN (?)", session["user_id"])
cash_left = float(cash_sql[0]["cash"])
return render_template("index.html", transactions_sql=transactions_sql, index=index, value=value, cash_left=cash_left)
HTML
{% extends "layout.html" %}
{% block title %}
Index
{% endblock %}
{% block main %}
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Symbol</th>
<th scope="col">Name</th>
<th scope="col">Shares</th>
<th scope="col">Current price</th>
<th scope="col">Total value</th>
</tr>
</thead>
<tbody>
{% for transaction in transactions %}
<tr>
<th scope="row">{{ transactions_sql.company_symbol }}</th>
<td>{{ index["name"] }}</td>
<td>{{ transactions_sql.SUM(shares) }}</td>
<td>{{ index["price"] | usd }}</td>
<td>{{ index["value"]| usd }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td class="border-0 fw-bold text-end" colspan="4">Current cash balance</td>
<td class="border-0 text-end">{{ cash_left | usd }}</td>
</tr>
<tr>
<td class="border-0 fw-bold text-end" colspan="4">TOTAL VALUE</td>
<td class="border-0 w-bold text-end">{{ cash_left | usd }}</td>
</tr>
</tfoot>
</table>
{% endblock %}
And here is my sqlite database :
sqlite> .schema
CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, username TEXT NOT NULL, hash TEXT NOT NULL, cash NUMERIC NOT NULL DEFAULT 10000.00);
CREATE TABLE sqlite_sequence(name,seq);
CREATE UNIQUE INDEX username ON users (username);
CREATE TABLE transactions(
transaction_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
company_symbol TEXT NOT NULL,
date DATETIME,
shares NUMERIC NOT NULL,
price NUMERIC NOT NULL,
cost NUMERIC NOT NULL,
id INTEGER,
FOREIGN KEY (id)
REFERENCES users (id));
Thanks in advance for your help !
The problem is the syntax of this sql:
SELECT company_symbol, SUM(shares) FROM transactions GROUP BY company_symbol WHERE id IN (?)
A GROUP BY clause comes after the WHERE clause.
Here is the doc for reference.

CS50 Finance: /index help displaying correct info

I've seen a few CS50 Finance help questions regarding /index. I'm trying to get the route to display a user's owned stock information (share number, value, price, etc.). Right now it displays the correct share amounts but does not display the name, value, or price (all blank). The "cash" and "grandTotal" amounts display but grandTotal is not the correct amount. I think I'm just confused on how to access specific values in my returns.
Python/sqlite:
def index():
"""Show portfolio of stocks"""
# sql queries to select stock info
user_id = session["user_id"]
stocks = db.execute("SELECT stock, symbol, SUM(shares) AS totalShares FROM purchases WHERE userid == :userid GROUP BY symbol", userid=user_id)
currentCash = db.execute("SELECT cash FROM users WHERE id == :userid", userid=user_id)
# Global variables to be updated
tableInfo = []
grandTotal = currentCash[0]["cash"]
#Grabbing info from each owned stock
for stockInfo in stocks:
symbol = stocks[0]["symbol"]
shares = stocks[0]["totalShares"]
name = stocks[0]["stock"]
currentStock = lookup(symbol)
price = currentStock["price"]
value = price * shares
grandTotal += value
tableInfo.append(stockInfo)
# Display a table with portfolio info for current user
return render_template("index.html", tableInfo=tableInfo, grandTotal=usd(grandTotal), currentCash=usd(currentCash[0]["cash"]))
HTML:
{% extends "layout.html" %}
{% block title %}
Your Portfolio
{% endblock %}
{% block main %}
<table class="table">
<thead>
<tr>
<th scope="col">Stock</th>
<th scope="col">Number of shares</th>
<th scope="col">Current price</th>
<th scope="col">Total value</th>
</tr>
</thead>
<tbody>
{% for stock in tableInfo %}
<tr>
<td>{{ stock.name }}</td>
<td>{{ stock.totalShares }}</td>
<td>{{ stock.price }}</td>
<td>{{ stock.value }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<table class="table">
<thead>
<tr>
<th scope ="col">Cash remaining</th>
<th scope ="col">Grand total</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ currentCash }}</td>
<td> {{ grandTotal }}</td>
</tr>
</tbody>
</table>
{% endblock %}

can't make index function work in cs50 finance

I am completely stuck in making index function work in cs50 finance! This function should return in a html page a table with the details of the transactions made online (details are saved in a database). But it's not working: even if there is a transaction in my database, my function doesn't find it, the table is empty.
this is my code:
def index():
"""Show portfolio of stocks"""
rows = db.execute("SELECT symbol, price, shares FROM transactions WHERE id = :user_id", user_id=session["user_id"])
transactions_info = []
total_worth = 0
for transaction_info in rows:
symbol = rows [0]["symbol"]
shares = rows [0]["shares"]
price = lookup(symbol)
worth = shares * price ["price"]
total_worth += worth
transactions_info.append(transaction_info)
return render_template("index.html", rows=rows, transactions_info=transactions_info)
And this is my HTML page:
{% extends "layout.html" %}
{% block title %}
Index
{% endblock %}
{% block main %}
<table class="table table-striped" style="width:100%">
<tr>
<th>Symbol</th>
<th>Company</th>
<th>Shares</th>
<th>Price</th>
<th>TOTAL</th>
</tr>
{% for transaction in transactions %}
<tr>
<td>{{ transaction_info.symbol }}</td>
<td>{{ transaction_info.name }}</td>
<td>{{ transaction_info.shares }}</td>
<td>{{ transaction_info.price }}</td>
<td>{{ transaction_info.worth }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
Thanks for your help!
In index() you are sending a list called transactions_info here
return render_template("index.html", rows=rows, transactions_info=transactions_info)
In the html you are looping over a list called transactions here {% for transaction in transactions %}.

How do I reduce the amount of queries of my Django app?

My app is currently making over 1000 SQL queries and taking around 20s to load the page. I can't seem to find a way to come up with a solution to get the same data displayed on a table in my template faster. I wan't to display 100 results so that's way my pagination is set to 100.
These are the methods in my my models.py used to get the count and sum of the orders, these two are in my Company model and the get_order_count is also in my Contact model
def get_order_count(self):
orders = 0
for order in self.orders.all():
orders += 1
return orders
def get_order_sum(self):
total_sum = 0
for contact in self.contacts.all():
for order in contact.orders.all():
total_sum += order.total
return total_sum
views.py
class IndexView(ListView):
template_name = "mailer/index.html"
model = Company
paginate_by = 100
template
{% for company in company_list %}
<tr id="company-row">
<th id="company-name" scope="row">{{ company.name }}</th>
<td>{{ company.get_order_count }}</td>
<td id="order-sum">{{ company.get_order_sum|floatformat:2 }}</td>
<td class="text-center">
<input type="checkbox" name="select{{company.pk}}" id="">
</td>
</tr>
{% for contact in company.contacts.all %}
<tr id="contact-row">
<th scope="row"> </th>
<td>{{ contact.first_name }} {{ contact.last_name }}</td>
<td id="contact-orders">
Orders: {{ contact.get_order_count }}
</td>
<td></td>
</tr>
{% endfor %}
{% endfor %}
Your two methods are very inefficient. You can replace them with annotations which calculate everything in one query in the database. You haven't shown your models, but it would be something like:
class IndexView(ListView):
template_name = "mailer/index.html"
model = Company.objects.annotate(order_count=Count('orders')).annotate(order_sum=Sum('contacts__orders__total'))
paginate_by = 100
Now you can access {{ company.order_count }} and {{ company.order_sum }}.

Creating an HTML table with database values in Flask

I want to display a table showing the values of three fields for each of the units in a table. Some assistance with creating the dictionary from the database and passing objects to the template would be greatly appreciated.
#app.route('/')
def index(row):
unit_count = Units.query.count()
unit = Units.query.filter_by(id=row).first()
rows = [] # Unsure how to define rows from Units db table
return render_template('table_overview.html', title='Overview', rows=rows, unit=unit)
{% for row in rows %}
<tr>
<td>{{ row.unit.idnum }}</a></td>
<td>{{ row.unit.product_code }}</td>
<td bgcolor="{{ row.unit.stat_colour }}">{{ row.unit.unit_status }}</td>
</tr>
{% endfor %}
First off your view function can't receive the row input you specify. If you're trying to show all rows in the table you can do it like this:
views.py:
#app.route('/')
def index():
rows = Units.query.all()
return render_template('table_overview.html',
title='Overview',
rows=rows)
table_overview.html (template)
{% for row in rows %}
<tr>
<td>{{ row.idnum }}</a></td>
<td>{{ row.product_code }}</td>
<td bgcolor="{{ row.stat_colour }}">{{ row.unit_status }}</td>
</tr>
{% endfor %}

Categories