I would like to ask for your help please with an error I keep getting on my code for the Finance problem. I can't seem to find a solution for it :/
I keep receiving:
:) application.py exists
:) application starts up
:) register page has all required elements
:) registering user succeeds
:) registration with an empty field fails
:) registration with password mismatch fails
:) registration rejects duplicate username
:) login page has all required elements
:( logging in as registered user succceeds
expected status code 200, but got 400
This is my code for application.py:
import os
from cs50 import SQL
from flask import Flask, flash, redirect, render_template, request, session, url_for
from flask_session import Session
from tempfile import mkdtemp
from werkzeug.exceptions import default_exceptions
from werkzeug.security import check_password_hash, generate_password_hash
from helpers import apology, login_required, lookup, usd
# Configure application
app = Flask(__name__)
# Ensure responses aren't cached
@app.after_request
def after_request(response):
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
response.headers["Expires"] = 0
response.headers["Pragma"] = "no-cache"
return response
# Custom filter
app.jinja_env.filters["usd"] = usd
# Configure session to use filesystem (instead of signed cookies)
app.config["SESSION_FILE_DIR"] = mkdtemp()
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)
# Configure CS50 Library to use SQLite database
db = SQL("sqlite:///finance.db")
@app.route("/")
@login_required
def index():
"""Show portfolio of stocks"""
# Query database stocks database for total number of shares of each stock owned by user
securities = db.execute("SELECT symbol, SUM(shares) FROM stock WHERE userid = :userid GROUP BY symbol",
userid=session["user_id"])
# Add current price and total value to each row; calculate total securities value
securities_value = 0.0
for security in securities:
# try 10 times to get quote -- often no value is returned
for i in range(0, 10):
quote_value = lookup(security["symbol"])
if not quote_value == None:
break
if quote_value == None:
security["current_price"] = 0
else:
security["current_price"] = round(float(quote_value["price"]), 2)
security["total_value"] = round(security["current_price"] * int(security["SUM(shares)"]), 2)
securities_value += security["total_value"]
# Query database for current cash balance
rows = db.execute("SELECT * FROM users WHERE id = :userid", userid=session["user_id"])
if not rows:
return apology("error retreiving cash balance", 400)
cash_balance = rows[0]["cash"]
# Calculate total portfolio value
portfolio_value = round(securities_value + cash_balance, 2)
return render_template("index.html", securities=securities, securities_value=securities_value, cash_balance=cash_balance,
portfolio_value=portfolio_value)
@app.route("/buy", methods=["GET", "POST"])
@login_required
def buy():
"""Buy shares of stock"""
#Make sure user arrives via post
if request.method == "POST":
stock = lookup(request.form.get("symbol"))
if stock == None:
return apology("invalid ticker symbol")
try:
shares = int(request.form.get("shares"))
except:
return apology("must be a number")
#Make sure number of shres is positive
if shares < 0:
return apology("input positive number")
rows = db.execute("SELECT cash FROM users WHERE id = :user_id",
user_id=session["user_id"])
available_cash = rows[0]["cash"]
price = stock["price"]
total_price = shares * price
if available_cash < total_price:
return apology("insufficient funds")
db.execute("UPDATE users SET cash = cash - :total_price WHERE id = :user_id", total_price=total_price, user_id=session["user_id"])
db.execute("INSERT INTO 'transactions' (user_id, symbol, shares, price) VALUES (:user_id, :symbol, :shares, :price)", user_id=session["user_id"], symbol=request.form.get("symbol"), shares=shares, price=price)
return redirect("/")
else:
return render_template("buy.html")
@app.route("/history")
@login_required
def history():
"""Show history of transactions"""
transactions = db.execute(
"SELECT symbol, shares, price_per_share, created_at FROM transactions WHERE user_id = :user_id ORDER BY created_at ASC", user_id=session["user_id"])
return render_template("history.html", transactions=transactions)
@app.route("/funds/add", methods=["GET", "POST"])
@login_required
def add_funds():
if request.method == "POST":
try:
amount = float(request.form.get("amount"))
except:
return apology("amount must be a real number", 400)
db.execute("UPDATE users SET cash = cash + :amount WHERE id = :user_id", user_id=session["user_id"], amount=amount)
return redirect(url_for("index"))
else:
return render_template("add_funds.html")
@app.route("/change_password", methods=["GET", "POST"])
@login_required
def change_password():
"""Allow user to change her password"""
if request.method == "POST":
# Ensure current password is not empty
if not request.form.get("current_password"):
return apology("must provide current password", 400)
# Query database for user_id
rows = db.execute("SELECT hash FROM users WHERE id = :user_id", user_id=session["user_id"])
# Ensure current password is correct
if len(rows) != 1 or not check_password_hash(rows[0]["hash"], request.form.get("current_password")):
return apology("invalid password", 400)
# Ensure new password is not empty
if not request.form.get("new_password"):
return apology("must provide new password", 400)
# Ensure new password confirmation is not empty
elif not request.form.get("new_password_confirmation"):
return apology("must provide new password confirmation", 400)
# Ensure new password and confirmation match
elif request.form.get("new_password") != request.form.get("new_password_confirmation"):
return apology("new password and confirmation must match", 400)
# Update database
hash = generate_password_hash(request.form.get("new_password"))
rows = db.execute("UPDATE users SET hash = :hash WHERE id = :user_id", user_id=session["user_id"], hash=hash)
# Show flash
flash("Changed!")
return render_template("change_password.html")
@app.route("/login", methods=["GET", "POST"])
def login():
"""Log user in."""
# forget any user_id
session.clear()
# if user reached route via POST (as by submitting a form via POST)
if request.method == "POST":
# ensure username was submitted
if not request.form.get("username"):
return apology("must provide username", 400)
# ensure password was submitted
elif not request.form.get("password"):
return apology("must provide password", 400)
# query database for username
rows = db.execute("SELECT * FROM users WHERE username = :username", username=request.form.get("username"))
# ensure username exists and password is correct
if len(rows) != 1 or not check_password_hash(request.form.get("password"), rows[0]["hash"]):
return apology("invalid username and/or password", 400)
# remember which user has logged in
session["user_id"] = rows[0]["id"]
# redirect user to home page
return redirect(url_for("index"))
# else if user reached route via GET (as by clicking a link or via redirect)
else:
return render_template("login.html")
@app.route("/logout")
def logout():
"""Log user out"""
# Forget any user_id
session.clear()
# Redirect user to login form
return redirect(url_for("index"))
@app.route("/quote", methods=["GET", "POST"])
@login_required
def quote():
"""Get stock quote."""
if request.method == "POST":
#Get stock information
stock = lookup(request.form.get("symbol"))
#Validate ticker symbol
if stock == None:
return apology("invalid ticker symbol")
return render_template("quoted.html", stock=stock)
else:
return render_template("quote.html")
@app.route("/register", methods=["GET", "POST"])
def register():
"""Register user"""
#User reached route via POST
if request.method == "POST":
#User entered username
if not request.form.get("username"):
return apology("must provide username")
#User entered password
elif not request.form.get("password") or not request.form.get("confirmation"):
return apology("must provide password")
#Confirm password matches
elif request.form.get("password") != request.form.get("confirmation"):
return apology("password must match")
#Hash the password
hash = generate_password_hash(request.form.get("password"))
#Insert user into database
result = db.execute("INSERT INTO users (username, hash) VALUES (:username, :hash)",
username=request.form.get("username"), hash=hash)
if not result:
return apology("username already exists")
else:
return redirect(url_for("index"))
#Remember user
session["user_id"] = result
#User reached route via GET
else:
return render_template("register.html")
@app.route("/sell", methods=["GET", "POST"])
@login_required
def sell():
"""Sell shares of stock"""
if request.method == "POST":
stock = lookup(request.form.get("symbol"))
if stock == None:
return apology("invalid ticker symbol")
try:
shares = int(request.form.get("shares"))
except:
return apology("must be a number")
if shares < 0:
return apology("input positive number")
available_shares = db.execute("SELECT SUM(shares) as total_shares FROM transactions WHERE user_id = :user_id and symbol = :symbol GROUP BY symbol",
user_id=session["user_id"], symbol=request.form.get("symbol"))
if available_shares[0]["total_shares"] < 1 or shares > available_shares[0]["total_shares"]:
return apology("not enough shares")
price = stock["price"]
total_price = shares * price
db.execute("UPDATE users SET cash = cash + :total_price WHERE id = :user_id", user_id=session["user_id"], total_price=total_price)
db.execute("INSERT INTO 'transactions' (user_id, symbol, shares, price) VALUES(:user_id, :symbol, :shares, :price)", user_id=session["user_id"], symbol=request.form.get("symbol"), shares=-shares, price=price)
return redirect("/")
else:
available_stocks = db.execute("SELECT symbol, SUM(shares) as total_shares FROM transactions WHERE user_id = :user_id GROUP BY symbol", user_id=session["user_id"])
return render_template("sell.html", available_stocks=available_stocks)
def errorhandler(e):
"""Handle error"""
return apology(e.name, e.code)
# listen for errors
for code in default_exceptions:
app.errorhandler(code)(errorhandler)
application raised an exception (see log for details)
– DinoCoderSaurus May 3 '19 at 17:39check_password_hash
in the login function (notpwd_context.verify
). Suggest you change that line. Out of curiosity: from where or when did you download the distro code? That particular line is from the CS50x 2017version. – DinoCoderSaurus May 3 '19 at 18:03transactions
records, sostocks
andquotes
are empty when sent toportfolio.html
– DinoCoderSaurus May 3 '19 at 18:35