1

Can't figure this out. My code passes functionality it buys stocks no problem but fails check50 with this error:

:( buy handles valid purchase
application raised an exception (see log for details) 

Log 
sending POST request to /login 
sending POST request to /buy 
exception raised in application: TypeError: 'NoneType' object is not subscriptable 

.

@app.route("/", methods = ["GET"])
@login_required
def index():
user = session.get("user_id")
rows = db.execute("Select Stock, sum(Num) as Number from portfolio where User = :User group by Stock having sum(Num) > 0", User = session.get("user_id"))
stocks = rows

currentprices = []
# get current price for each group (ie AAPL) with help from lookup function (which remember, returns a dict)
for stock in stocks:
    symbol = str(stock["Stock"])
    currentprices.append(usd(round((lookup(symbol)['price']),2)))
totals = []
totals1 = []
# get current price for each group (ie AAPL) with help from lookup function (which remember, returns a dict)
for stock in stocks:
    symbol = str(stock["Stock"])
    p = round(float(lookup(symbol)['price']),2)
    n = round(float(stock["Number"]),2)
    t = round(p*n,2)
    totals.append(usd(t))
    totals1.append(t)

#get cash
rows = db.execute("Select cash from users where id = :User", User = session.get("user_id"))
cash = round(float(rows[0]["cash"]),2)

gotal = round(sum(totals1)+cash,2)


return render_template("index.html", stocks = stocks, prices = currentprices, totals = totals, cash = usd(cash), gotal = usd(gotal))




@app.route("/buy", methods=["GET", "POST"])
@login_required
def buy():
"""Buy shares of stock"""
if request.method == "POST":

    # Ensure buy order
    if not request.form.get("symbol"):
        return apology("must provide valid order info", 400)

    # Ensure buy order
    elif not request.form.get("shares"):
        return apology("must provide valid order info", 400)


    # Ensure stock is balid else display an apology
    elif lookup(request.form.get("symbol")) == None:
        return apology("invalid stock", 400)

    # Add stock to user's portfolio

    stock = lookup(request.form.get("symbol"))['name']
    num = request.form.get("shares")
    price = (lookup(request.form.get("symbol"))['price'])
    user = session.get("user_id")
    amount = (float(request.form.get("shares")) * float(lookup(request.form.get("symbol"))['price']))

    # check if they have enough cash
    # Query database for username
    rows = db.execute("SELECT * FROM users WHERE id = :id", id = session.get("user_id"))
    rows = float(rows[0]["cash"])


    # Add trasnaction to portfolio if user has enough cash
    if (float(num) * float(price)) <= rows:
        result = db.execute("INSERT INTO portfolio (User, Stock, Price, Num) VALUES(:User, :Stock, :Price, :Num)", User = session.get("user_id"), Stock = stock, Price = usd(price), Num = num)
        if not result:
           return apology("TX did not recrod", 400)
#         Update cash
        result = db.execute("UPDATE users set cash = cash - :amount where id = :User ", User = session.get("user_id"), amount = amount)
        if not result:
           return apology("Cash did not update", 400)

     # Redirect user to home page
        return redirect("/")
    else:

        return apology("Not enough Cash", 403)
else:
    return render_template("buy.html")
1
  • In function buy you should add a condition for checking if the value of shares is positive.if the value of shares is negative your function may fail. Commented May 2, 2018 at 16:25

1 Answer 1

0

The error message says:

exception raised in application: TypeError: 'NoneType' object is not subscriptable

That usually means that you are using [] on an object which happens to be None.

Now I see that there are several places in your buy() function where you skipped to check a result before trying [] ...

For instance:

  • I see that you call lookup(request.form.get("symbol")) 4 times in a row. However, you throw away the result immediately ...
  • The second, third and fourth time you don't do any checks, but you immediately try to get a value from the result (assuming that those three calls succeeded again, and had an actual result again.

Now remember that that call results in a web request. Doing that 4 times instead of once is expensive (takes unnecessary time and resources). But doing it 4 times is also dangerous: In one of those last 3 calls fails, you'll get an IndexError.

Another example: After querying the database with rows = db.execute("SELECT * FROM users WHERE id = :id", id = session.get("user_id")), you immediately subscript the result, without checking whether you got any rows ...


Finally, to quote Cliff B:

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .