1

Answer

The error was in my index() implementation. I had made the mistake of including the following code in index():

    # 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"])
    if not securities:
        return apology("error retrieving securities", 400)

I now realize that the errors were because of this last if statement, which I didn't notice because I was logging in with an account that had securities purchased! Removing this if statement eliminated the error.

Thanks all!

Original query

I am having difficulty with check50's validation of my code.

In my initial version, the final line of code in the register() and login() functions for POST was:

return redirect("/")

Running check50, I got the following errors:

:( registering user succeeds
expected status code 200, but got 400
Log
sending POST request to /register
checking that status code 200 is returned...

:( registration rejects duplicate username
expected status code 200, but got 400
Log
sending POST request to /register
checking that status code 200 is returned...

I managed to "fix" the issue per PSET7 Finance - check50 error by rendering a blank html page with return render_template("blank.html") at the end of the register() function for POST, rather than using return redirect("/"). For clarity, I have created a blank.html page, which is simply a blank page. Making this change to register() resulted in check50 no longer returning an error message in the registration validation. NOTE Once I fixed index() per above, this change wasn't needed.

Now check50 gives me the following error:

:( logging in as registered user succceeds
expected status code 200, but got 400
Log
sending POST request to /login
checking that status code 200 is returned...
sending GET request to /
checking that status code 200 is returned...

I tried to similarly replace return redirect("/") at the end of the login() function for POST with return render_template("blank.html"). This did not eliminate this check50 error.

Any insight would be greatly appreciated!

Here is the current version of my register() and login() functions:

@app.route("/login", methods=["GET", "POST"])
def login():
    """Log user in"""

    # Forget any user_id
    session.clear()

    # 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", 403)

        # Ensure password was submitted
        elif not request.form.get("password"):
            return apology("must provide password", 403)

        # 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(rows[0]["hash"], request.form.get("password")):
            return apology("invalid username and/or password", 403)

        # Remember which user has logged in
        session["user_id"] = rows[0]["id"]

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

    # User reached route via GET (as by clicking a link or via redirect)
    else:
        return render_template("login.html")

@app.route("/register", methods=["GET", "POST"])
def register():
    """Register user."""

    # Forget any user_id
    session.clear()

    # 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 and confirmation were submitted
        if not request.form.get("password") or not request.form.get("confirmation"):
            return apology("must provide password", 400)

        # Ensure password and confirmation are the same
        if not request.form.get("password") == request.form.get("confirmation"):
            return apology("password and password confirmation must match", 400)

        # Insert username into database and check for error
        result = db.execute("INSERT INTO users (username, hash) VALUES (:username, :passwordhash)",
                            username=request.form.get("username"),
                            passwordhash=generate_password_hash(request.form.get("password"),
                                                                method='pbkdf2:sha256', salt_length=8))
        if not result:
            return apology("username already taken, choose a different username", 400)

        # Remember which user has logged in
        session["user_id"] = result

        # Load blank page (redirect will make check50 fail) -- would prefer to use return redirect("/")
        return render_template("blank.html")

    # User reached route via GET (as by clicking a link or via redirect)
    else:
        return render_template("register.html")

Here is my code for index():

@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"])
    if not securities:
        return apology("error retrieving securities", 400)

    # 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)
1
  • Maybe some mistake on your index?
    – Blauelf
    Commented Jun 6, 2018 at 20:14

2 Answers 2

3

This is pointing to a problem with your index.html page. Have you completed your index function? If not, why are you running check50 which should be used as a final check once you've completed the problem?

The check50 tests assume that all parts of the problem have been completed.

3
  • Thanks for your response. I did implement index(). In case I made a mistake of some sort, I've included the code for index() and the markup for index.html in my question.
    – Ryan
    Commented Jun 7, 2018 at 23:39
  • In your index, you say: if not securities: return apology("error retreiving securities", 400) Why are you returning 400 if the user hasn't purchased any stocks yet? That would certainly be the case when a user has just registered.
    – curiouskiwi
    Commented Jun 7, 2018 at 23:40
  • thank you curiouskiwi! that was my error...
    – Ryan
    Commented Jun 8, 2018 at 0:16
1

You can "check50" login and register without completing index.html....as long as it doesn't return a 400. If you examine the apology function in helpers.py, you will notice that the code parameter is optional and defaults to 400. If you change return apology("TODO") in index (which returns a 400 by default) to return apology("TODO",200) you will be able to test register independently while using return redirect("/").

Another option would be to write a "placeholder" index.html and redirect to that in the "/" route.

The only explanation I can think of as to why return render_template("blank.html") doesn't work is that blank.html does not exist.

0

You must log in to answer this question.

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