SPEAKER 1: In this problem, your task is going
to be to design a web application that allows
users to manage a portfolio of stocks.
In order to do so, you'll need to implement
a variety of different features.
First, you'll need to make sure that every user can register for an account.
Once they register for an account, a user
should have the ability to look up a stock quote,
buy a stock if they want to, see an index page that
shows them all of the stocks the current user is bought,
then the user should be able to sell any of the stocks that they currently own,
and see a history of all of their transactions.
And finally, once you've implemented all of these features,
you'll implement a personal touch of your very own to add to this website
application.
But before we dive into the features that you're going to implement,
let's start by taking a look at the distribution code that will
provide to you as a starting point.
For this problem, the distribution code for this problem
comes in a number of different parts.
We'll give you a few Python files, app.py, and helpers.py, in addition to
a SQLite database called finance.db.
In addition, we'll also give you a folder filled with templates.
And we'll walk through each of these parts of the distribution code
one file at a time.
Let's start with app.py, which is where you'll write most of your Python code
for this web application.
App.py defines a Flask web application, and also defines
a variable called db, which will allow you to connect to a SQL database.
In particular, you can use the function db.execute
to execute a SQL statement on your SQL database.
Later in app.py, you'll also see definitions
for each of the routes inside of your web application.
Each of which will start with the syntax @app.route.
These routes can take a variety of different request methods.
Most notably for getting the contents of a page and post
generally used if you're submitting data to a particular route.
There are some routes that have already been implemented
for you, such as log in and log out.
And let's now take an opportunity to look at one of these routes, the login
route, just to get a sense for how routes in Flask
this web framework actually work.
So here is the login route, and it begins
with this syntax, @app.route with slash login being the route
that users can use to access this part of your web application.
This particular route accepts two different methods, GET and POST.
And it's associated with this function called login.
Because the login route accepts to request methods, GET and POST,
and we need to make different decisions based on that request method,
one of the first things we'll need to do is check what the request method is.
If the request method is POST, that means the user has just
submitted the login form.
And if the user has just submitted the login form,
then we'll need to access whatever data the user typed into that form.
In order to do that, we can use this syntax here, reques.form.getusername,
to get whatever the current username is that the user typed in into that form.
And if the user didn't provide a username,
well then we should render an apology.
An error message to the user to let them know
that they need to provide a username.
Likewise, just as we make sure that the user has typed in a username,
we also need to make sure that the user has typed in a password.
And if the user didn't type in a password,
then we should render an apology as well.
After that, once we're sure that the user has
typed in both a username and a password, we
need to now look them up inside of our finance.db database
to make sure that this is a valid username and password combination.
So we'll use db.execute to run a select query on our existing database,
and do a SELECT to try and find the user whose username is equal to whatever
it is the user typed in into the form.
We won't know what the user name is until the user actually
types in their username and clicks the button to submit the form.
And so here, we're using a question mark,
where the question mark is acting as a placeholder for whatever the user typed
into the form, which again, we can access
via this syntax, request.form.get.
Whenever we run the execute function on a select query running
on our database, what we'll get back is a list of all of the rows
that matched our SELECT query.
So the next thing we should do is check to make sure that what we got
back is exactly one row representing that particular user,
and we should check to make sure that their password was correct.
If either of those isn't true, if the user is not in the database,
or they typed in their password wrong, well then
we should return an error back to the user using that apology function
to let the user know that this was an invalid username and password
combination.
And if we made it through all of that, that
means the user has typed in a username and a password,
and we verified that this is a valid username password combination.
And if that's the case, then the next thing we should do
is actually log the user in.
How do we do that, we'll recall that we can
use the session variable to keep track of information about the current user.
So we'll store inside of session bracket user ID, the current user's ID
that we got from the database.
And after we've signed the user in, we'll
go ahead and redirect the user back to the home page.
So that they can now go ahead and look up stocks
buy stocks or sell stocks if they would like to.
And finally, at the very end of the function,
we need to take care of the other request method.
All of that code we just took a look at was if the request method was POST.
The user actually submitted the login form.
But if instead the request method is GET,
that means the user just clicked on a button to access the login form.
And in order to do that, what we'll do is
return a template back to the user rendering the login
form so the user can go ahead and type in their username and password.
In addition to app.py, we also provide you
with helpers.py, which is a Python file that contains some useful functions
that you might take advantage of as you're
building the various features of this web application.
We'll give you a function called apology that
displays an error message to the user.
Login required can be used above any of your functions
to require that a user log in before they're able to access a given route.
For example, you might want to make sure that a user is logged in before they're
able to buy or sell stocks.
The lookup function, meanwhile, uses a stocks API to get the current stock
quote for a particular stock symbol.
So you can look up a stock buy it's symbol
and figure out what the current quote for that stock is.
And finally, we give you a function called USD that takes a number
and formats it as US dollars.
With a dollar sign, some number of dollars, and some number of cents.
Next in the distribution code is finance.db
and this is the SQLite database that is going to store all of the application
data for your web application.
So far in financ.db will give you a user's table.
And inside of this user's table, you'll find columns
for keeping track of each user's ID, their username,
a hash of their password, and how much cash that user has.
But you'll likely need to add new tables into this database
to finish implementing all of the features of the web application.
And you can do that using the CREATE TABLE syntax in SQL.
Finally, in this distribution code, we also
give you a folder of templates that contains HTML templates that
can be rendered to the user depending on what part of the web application
they're trying to access.
There's a file inside of your templates folder called layout.HTML
that defines the general HTML structure for all of your pages,
and then the rest of your HTML pages can use the syntax
to extend layout.HTML to use that existing layout
and add to it a title for the page and the main body content of each
of your other HTML pages.
Now that we've taken a look at the distribution code that
will provide to you for this problem, let's now turn our attention
to each of the different features that you'll
need to implement to make this web application fully functional.
The first thing you'll need to do is make sure
that each user has the ability to register for your finance application.
In order to do that, your register route should accept two different request
methods, GET and POST.
If the user tries to access the register route using the GET request method,
then you should just display a form to the user.
So that they can register for a new account.
Once the user submits that form, accessing your register route
via the POST request method, what you should do is check for possible errors.
And if there are no errors, then you can insert the new user into the user's
table and log the user in after that.
So let's start with that registration form.
How will you display a registration form to the user?
Well in order to do that, you'll likely need
to create a new template that contains the HTML for that registration form.
And recall that you can find all of your templates inside
of that templates folder in your finance directory.
You can use the login.HTML template that we've already
provided to you as inspiration for what this new template might look like.
And remember, the HTML form that you create
should contain input fields that allow the user to choose a username,
choose a password, and then verify that they typed in their password correctly.
Once the user types in information into that registration form
and submits it to your website application,
your Python code is going to need to access whatever it is the user typed
in to that registration form.
In order to do that, you can use some syntax like this.
If you have an input field inside of your HTML code
with an attribute that says name equals password, for example.
Well then inside of your Flask application,
inside of your Python code, you can use this syntax here,
request.form.get, and then the name of that input field, in this case,
password.
And that will allow you to access whatever
it is the user typed into the form, and then
submitted via the POST request method.
You can do that for the password, for the confirmation,
and for the user's username as well.
Inside of your route, you'll also want to check for possible errors.
What might go wrong when the user is trying to register for a new account
Well, if any field is left blank, if the user didn't type in a username,
didn't provide a password, or didn't confirm their password,
you should return an apology, letting the user know that each of those fields
was required.
If the two passwords don't match with each other,
you should also let the user know that as well.
And finally, if the user name is already taken by some other user
already inside of your database, you should apologize to the user
and let them know about that as well.
Once you've confirmed that there are no errors with what the user provided
to you, you'll want to add the user to the user's table of your database,
but you should keep security in mind as you do so.
In particular, remember the databases should never store plaintext passwords.
Instead, you should first generate a hash
of the user's password using the Generate password hash
function provided to you.
And then store the hash of the password inside of the database instead
of the plaintext password itself.
Once you've generated a hash of the password,
then you can add all of this information into the database
by using db.execute in order to run an insert statement
to add a new row into the user's table.
And remember again, you can use the question mark symbol
to stand in as a placeholder for a value that you might not know yet at the time
that you're writing this code.
Once the user has been added into the user's table,
then you can log the user in.
Setting session, bracket user ID, equal to the new ID for whatever user
you've just added to the database.
Once the user has been able to register for an account,
next, you'll want to allow the user to look up stock quotes.
In your quote route, you should also accept to request methods,
GET and POST.
If a user tries to access your quote route via GET,
you should display a form that lets the user request a stock that they
would like to look up.
And when the form is submitted via POST, then your application
should look up that stock symbol by calling the lookup function
and display the results back to the user.
How does the lookup function work?
Will recall that lookup is a function that we have
defined for you inside of helper.py.
And it takes a stock symbol and returns a stock quote.
If lookup was able to successfully look up the stock quote,
then the function is going to return a dictionary back to you
with fields to represent the name of the stock, the symbol for that stock,
and what the stock's current price is.
But it's also possible that the lookup will not be successful.
If for example, the user tries to type in a stock symbol that doesn't exist.
In that case, you should return an apology
to the user letting them know that particular stock symbol doesn't exist.
But if the lookup is successful, what you'll
want to do is display an HTML page to the user that contains information
about the stock, the name of the stock, and what
the current price of that stock is.
In order to do so, you'll need to pass in values into your HTML template.
And how might you do that?
Well, in your Python code, you can use the render template function
to render an HTML template, but you can also
provide variables into this template that's known as a jinja template.
For example, in this code here, I'm rendering Hello.HTML,
but giving this template access to a variable
called name, which in this case is equal to Brian.
And then inside of my jinja template, I can use double curly braces
around the variable name.
In this case, name, in order to display whatever
was passed in from the render template function here inside of my HTML.
Likewise, you could do something like this as well in order
to display the current price of whatever stock the user has just looked up.
In addition to allowing users to look up a stock quote,
we also want to allow users to buy a new stock.
In order to do that, your buyer out will also accept to request methods GET,
and POST.
Where when the user gets this page they should
be shown a form that allows the user to buy a stock.
And when the user submits that form, you should purchase the stock as long
as the user can actually afford it.
Your HTML form should allow the user to type in what stock symbol
they would like to buy, in addition to how many shares they would like to buy.
Once the user submits the form, you'll want to check it for valid input.
For example, a user shouldn't be allowed to by a negative number of shares.
And you'll also want to make sure that the stock symbol is actually valid.
But before you can add this data into your database,
you'll likely need to create one or more new tables
to keep track of this new information.
Right now the finance.db database we provide
to you includes a table for keeping track of users
and how much cash they have but doesn't include
any tables for keeping track of what stocks each of those users
actually owns.
So you'll first want to give some thought as to what new tables
you'll want to add to this database, and what
fields that table or tables will have.
You can use the CREATE TABLE statement to add a new table to the database,
and you'll want to be sure to use appropriate SQL types as you do so.
There are multiple correct ways to implement this.
So decide for yourself what kind of database design
makes the most sense to you and is most logical for this particular web
application.
Once you're happy with the tables inside of your database,
you'll want to add this new stock purchase to the user's portfolio.
First, remember that you'll need to make sure the user has enough cash
to afford the stock.
If the user can't afford the number of shares of the stock
that they're trying to purchase, you should return an apology
to the user letting them know that they don't
have enough cash for this purchase.
But assuming the user does have enough cash for the purchase,
you should run whatever SQL statement you need on your database
to purchase that stock, and also be sure to update that user's cash to reflect
the purchase that they've just made.
Once you've implemented this feature, users
should be able to log into your web application and buy new stocks.
But once users have bought those new stocks it would be nice
if there was a place where users could view all of the stocks
they've already bought, and that's what you'll do in this next feature.
The index page of your application should display an HTML table
with all of the information about all of the stocks
that the current user owns, how many shares of each stock
the user owns, the current price of each of those stocks,
as well as the total value for each of those holdings.
For example, if the user has multiple of a certain stock,
their total value for that stock will be higher.
You should also display the user current cash balance on this page,
as well as their grand total of the combination
of the value of all of their stocks and whatever
cash they happen to have on hand.
As you create this HTML table, you'll realize that there's
some HTML that you're going to repeat.
For example, you might have one row for one stock,
and a very similar row for another stock.
And again and again for each of the stocks that the user currently owns.
In order to render this as HTML, it might
be nice to have some kind of a loop where
you're looping over all of the stocks, adding 1 row of the table for each
of the stocks the user currently owns.
And it turns out we can use loops like this inside of a jinja template.
In this example, we return render template Hello.HTML,
and then also pass into that HTML template a list of Python dictionaries.
Then inside of our jinja template we're able to loop over
each one of those dictionaries for contact in contacts
and then use dot notation inside of the template to access
any of the fields of that dictionary.
Dot name or dot house, in this particular example.
And you might imagine doing something similar in your own index page.
First, using the database and the lookup function
to look up all of the information you need about the stocks
that the current user has, and then looping over all of them
inside of your HTML template displaying one row of a table for each stock
that the user currently owns.
Users now have the ability to buy new stocks
and see an index of all of the stocks they currently own.
So next, let's give users the ability to sell a stock.
When the user tries to request your cell route via GET,
you should display a form that allows the user to choose which of the stocks
they currently own that they would like to sell,
and how many shares of that stock they would like to sell.
And when the user submits that form via POST,
you should check for possible errors, and then
sell the specified number of shares of that stock,
and update the user's cash balance to reflect that sale.
What kind of errors might come up?
Well for example, you want to make sure that the user actually
has the number of shares of stock they're trying to sell,
and you want to make sure that the user can't sell a negative number of shares.
With all of these features, users now have the ability
to buy and sell stocks.
But let's now give users the ability to see
a history of all of their previous transactions on your application.
When the user accesses the history route,
you should display to the user in HTML table
with all of their previous transactions, with one row for every buy
or sell including information about what stock was bought or sold,
how many shares of that stock were bought or sold,
and when that transaction actually took place.
How you implement the history functionality in your web application
will depend on how you've designed your database, what tables there are,
and what columns each table has.
And it's possible that you might need to revisit and revise
your existing database structure to allow for this new history feature.
Once you've implemented all of those features, the last thing you'll do
is add a personal touch to your website application
by deciding a new feature of your own that you'd like to implement
and adding it to CS 50 finance.
For example, you might allow users to change their password,
or you might allow users to add new cash into their account,m or you can choose
something else entirely.
Deciding on a feature you would like for this web application to have
and designing new route, templates, or tables as
needed to make that functionality possible.
Once you've completed that you'll have a fully functional web
application, allowing users to register, sign into their account,
buy and sell stocks, and see a history of all of their transactions.
My name is Brian, and this was CS 50 finance.