CARTER PAGE: Welcome to this CS50 seminar,
Publishing Your Flask App to the Web.
My name's Carter Page, and I'm here in New Haven, Connecticut,
at Yale University.
And today we're going to talk about life outside the CS50 IDE.
Now, there comes a time when the baby bird must leave the nest.
And likewise, it is time for your CS50 Flask app
to leave the nest of the CS50 IDE and fly on its own
in the big wide world of the internet to become the next big Facebook.
Now, in this seminar, we're going to walk through the steps
to take your Flask app running happily in the CS50 IDE to a standalone web app
that millions of people can visit across the globe.
Now, along the way, we're going to learn about a ton of different tools,
including Heroku, GitHub, Terminal, Postgres, Homebrew,
Atom, and many more.
Now, all these tools, each of them, you could do your own seminar about.
But today, our goal is just to introduce you
to a ton of different tools along the way so you can get a sample of those
and so you can go back on your own and learn more about them.
And before we start, life outside the CS50 IDE can be very frustrating.
But I urge you to stick with it.
My best advice is to roll up your sleeves, get ready to Google for help,
ask for help on Stack Overflow, and be prepared to face
some mind-numbing error messages.
In this seminar, we divide publishing your Flask app to the web
into five different parts.
Part one is taking your Flask app from the CS50 IDE
and pushing that up to GitHub.
Part two is taking the files that we've pushed up to GitHub
and bringing them down to your local Mac computer.
Part three is our database tire change.
Much like NASCAR, where you have the cars racing around
and they need to switch out the tires, part three for us
is where we're going to switch out the SQLite database that we use in the CS50
IDE, and replace it with Heroku Postgres that'll
be able to work better with Heroku when we publish the app onto the web.
Part four is taking the files in the Flask app running locally on your Mac
and pushing that up to Heroku, and then part five--
and it's the easiest one-- is taking it from Heroku to the worldwide web.
So let's get started.
So part one is taking our stuff from the CS50 IDE
and pushing those files up to GitHub.
Now, to begin, you want to log in to your CS50 IDE and cd
into your project directory.
We're going to start off by getting our Flask app out of the CS50 IDE.
To do so, we're going to upload the files to the website GitHub,
using this thing called git.
So cd to the project.
Then you're going to run the command git init.
So git init basically initializes an empty repository.
Now, git add, you're going to do git add dot,
and that period represents the current working directory.
So when you do git add dot, you're meaning,
let's load up these files in the current working directory,
and let's get ready to send them off.
Now before you can send off these files, though, to GitHub, what you need to do
is do a commit.
You can think of commit as like a stamp of approval
that these files I've added and loaded up, we're ready to send them off.
So we git commit with a message "first commit,"
and we're ready to send them off.
Now, in order to send these files off from the CS50 IDE into GitHub,
we need to tell them where to go in GitHub, because GitHub's a big place.
So we need to get a URL from GitHub to send these files to.
So now what you need to do is log in to your GitHub account
and create a new repository.
And you should probably make your repository name something
similar to the directory that you're working with, to make things easier.
So once you finish creating your repository,
GitHub will give you these commands of a URL after git remote add origin.
So after you've created this repository, GitHub
will give you this URL after git remote add origin.
What you want to do is take that command,
git remote add origin, with the URL, and you want to run that in the CS50 IDE.
Your next step, then, will be to do git push, and the -u here is not necessary.
Git push origin master.
And what that will do is take the files that you added to load them up,
you committed them, sealed them, and that push
is the final standoff to GitHub.
So now we have successfully pushed the files from your CS50 IDE up to GitHub.
So great job on part one.
Part two now is taking the files that we've sent off to GitHub
and bringing them down onto your Mac.
What we now need to do is get your Mac ready
for these Flask app files that we've taken from the CS50 IDE to GitHub,
and we're now ready to bring them down to the Mac.
So we're going to have to pimp out your dev setup.
The first thing you need to do is get familiar with the Terminal app.
To find it, you can go to the spotlight feature of your Mac and type
in "terminal."
It'll pop up right away.
All Macs have Terminal pre-installed, so you have it
even if you've never used it before.
The first time you open up Terminal, you'll notice that hey,
this looks a lot like the command line prompt from the CS50 IDE.
And you're right, they're very similar.
But the only difference is that when you type "ls," for example,
you'll see the files on your own computer,
because the terminal, the file system that it's working with, this command
line prompt, is that of your own computer,
rather than CS50 IDE, which works with the files in your workspace.
So let's cd into desktop, and you can explore it
just like you did in the CS50 IDE.
So to prepare your Mac for your Flask app,
you're going to need to download many different tools--
and these tools are known as packages--
that our Flask app needs to run.
For example, you could think of, oh, we need Python.
We need Flask.
We need stuff to work with our database.
All these different tools, it's difficult to keep track of them.
And so there's this fantastic thing called
Homebrew, which is a package manager.
And we're going to be using that to keep track of it.
And Homebrew is a lifesaver.
Without it, it would be incredibly difficult to keep track of anything.
So to get Homebrew, you need to go to Homebrew's website.
And at their website, they have this command for you
to copy and paste into your terminal prompt.
And so you just take it, copy, paste it, and click Enter.
And it'll walk you through the installation process for Homebrew.
So Homebrew will take a little while to install,
because it's installing quite a bit.
But once you have it, you'll quickly see why it's fantastic.
So now that we have Homebrew, let's get git, because what we're trying to do
is take those files from GitHub and bring them down to our Mac using git.
So to get git, it's very simple.
Brew install git.
And you type that into your Terminal app, and voila, you'll have git.
Now, what we want to do now is take those files from GitHub
and bring them to the Mac.
So what we can do is do a cd to change directory,
home directory slash desktop, and then we
can run the command git clone, which basically means download files.
But we need to tell git where to get those files from, and that's the URL.
Now, to get this URL, you can go to any repository on GitHub,
and you can tap on that green button, Clone or Download,
and it'll give you a URL you can literally copy and paste right where I
have those brackets and URL filled in.
My recommendation for this walkthrough is
that you use the refo I provided in the Who Was Here Flask app that I've
put together for this demonstration.
So once you do git clone, now those files are on your desktop,
and you should be able to even look at your desktop
and you'll see the folder there.
And the folder name will be Who Was Here.
Now, let's keep going to building out our Mac development environment.
So for our Flask app, we're going to need Python.
And so let's do brew install python and then brew install python3,
because remember there's versions 2.7 and 3.6.
Homebrew keeps track of all the different tools that we're using
and are present on our Mac.
But keeping track of all the different dependencies and tools
that our specific Flask app is using, that's a whole other job.
And to do that, we're going to be using something called a virtual environment.
Virtual environments are ways for us to keep
track of the different tools, different dependencies,
that our Flask app is using.
So to get virtual environments-- you might be getting the hang of this--
brew install virtualenv, where "virtualenv"
stands for "virtual environment."
In the CS50 IDE, if you wanted to edit a file, you just clicked on it,
and then the file would pop up, and you could type
and you could make changes on it, et cetera, et cetera.
But on your Mac, there's no equivalent right now.
You just have the command line prompt to interact with the program.
What you can do is download what developers call text editors.
And there's many of them--
Sublime, Atom, and Atom's my personal preference,
so we're going to use that one for this walkthrough.
So to get Atom, you just go to Atom's homepage, atom.io,
and download it, just like you would any other program.
Now, once you have Atom installed, you can take a look
at the files in your Flask app by cding into the directory Who Was Here.
You always have to be in that directory.
And then you can type atom period.
And that period there stands for the current working directory.
So it opens up the current working directory in Atom.
And once you see this, you'll say, oh!
This is just like the CS50 IDE, where you can tap on files on the left side
and make changes to them, just like what we've been used to this semester.
Now things are going to start getting a bit more complicated.
So last time, we downloaded virtualenv, which
is the tool for us to make these virtual environments.
But now we need to actually make them.
To make one, make sure you cd into the project directory, which
is Who Was Here in your desktop, and type in "virtualenv -p python3 venv."
All right.
That's a mouthful.
What's going on here?
So virtualenv is the tool that we downloaded, we got from Homebrew,
to create virtual environments.
The -p python3 means we want our virtual environment
to use Python 3.6 by default, because that's
how we've been doing this in CS50 IDE.
And then venv is just the name of this virtual environment
that we're creating.
Venv, virtual environment.
Now, to turn our virtual environment into something that's useful--
because right now it's a virtual environment that's empty--
we need to first turn it on, or activate it, by source venv bin activate.
And then we're going to use pip, which is--
you know how Homebrew's like a package manager for programs
all over the computer?
Pip is very similar, but for Python.
So we're going to use pip to install the requirements listed
in that pesky requirements.txt file.
And so you can do that by typing pip install -r requirements.txt,
and that goes through and reads all the different packages listed
in the requirements.txt file, and downloads the ones you need.
And that concludes part two, taking the files from GitHub
and bringing them down onto our local computer.
Now, part three-- this is where it's the tricky one,
and this one's pretty frustrating.
This is the tire change, where we're switching the SQLite database that we
know and love from CS50 IDE, and we're switching it out for Heroku Postgres.
So right now, the program is looking for this thing
called DATABASE_URL to find the database that it's going to connect to.
But we haven't told it what DATABASE_URL is.
We're going to get that DATABASE_URL from Heroku.
So what is Heroku?
Heroku is a online platform that makes it really easy for developers
to publish web apps to the internet.
And to use Heroku--
you might have guessed it by now-- we're going
to be using Homebrew to brew get Heroku's command line
tools, which is heroku/brew/heroku.
Now, if you don't have a Heroku account, no worries if you don't.
Go sign up at the link that I've provided, signup.heroku.com.
And then once you have an account, go back to your terminal,
and do heroku login.
Change directory into Who Was Here, and then
this is where the fun part is-- heroku create.
And congratulations, you have successfully
made your Heroku web application.
The problem is it doesn't work at all right now.
And the reason for that is we still haven't done anything
about that database.
So another thing we need to take care of is
Heroku needs this thing called a Procfile in order to work.
Basically, the Procfile tells Heroku what type of application
we've sent to it and what command does it need to run to turn it on.
It's very easy to forget your Procfile, so make sure you don't.
If you get an error message from Heroku, first thing you can check
is, did you remember the Procfile?
The code that I've provided you already has a Procfile with it,
but if you're porting your own Flask application from CS50 IDE,
you're going to have to make your own.
And so the instructions to make it are pretty simple.
Do pip install gunicorn.
And remember, when you're pip installing,
make sure that you have the virtual environment activated.
Then we're going to do touch Procfile to create a Procfile,
and then inside of Atom or your editor, type in, for your Procfile,
simply "web: gunicorn space application:app."
Now, this is the most difficult part of the journey.
And this is switching out the SQLite we used in CS50 IDE for Heroku Postgres.
This step is going to take the most time for you on your own,
and it will require you to learn a bit more about Flask-SQLAlchemy
to find the answers for your specific database implementation.
But what I've done here is provided you with a sample app,
so you can see that, oh, switching this over, at first it may look strange,
but actually, it makes sense.
So the first thing we're going to do is pip install Flask-SQLAlchemy.
And now what we need to do is go through our application.py file
and remove the references to SQLite.
For example, from CS50 import SQL, db equals SQL space--
or SQL parenthesis SQLite, because we're not going to be using SQLite anymore.
Next, what we're going to be replacing it with--
and don't be intimidated at first--
is SQLAlchemy.
And specifically, what we're going to be replacing it with is Flask-SQLAlchemy.
And if you look at this, import OS is something that
helps us get environment variables.
From Flask-SQLAlchemy import SQLAlchemy.
That's very similar to the from CS50 import SQL.
Next, this app.config SQLALCHEMY_TRACK_MODIFICATIONS,
that part, yeah, that's confusing.
That's just a warning that if you don't have it, you'll get that warning.
So just listen to the computer, and just put it in.
Then you have an app.config step, which basically
allows us to use the environment variables DATABASE_URL
to find the database.
For this example application, Who Was Here, it's very simple.
You go onto a website and there's a form, and you type in your name,
and you press Submit.
And then your name shows up in a list of other people who have been there.
So a very simple application.
Now, if you look at this class implementation,
we see that we have User, which is pretty similar to, oh,
that's the name of our table.
And you see, oh, ID equals db.Column.
That's a column in our table.
And Name is another column.
And ID is an integer, Name is a string, and so you can piece together, oh, this
actually isn't that bad.
We've seen stuff like this.
But it's just in a different format.
Another thing we need to go through and remove
are these db.execute statements, because we're
going to be using Flask-SQLAlchemy directly, rather than using it
through the CS50 library.
So if we go out and remove those db.execute statements,
we're going to be replacing it with something that at first looks
really different, but actually it's pretty similar
when you go through the steps.
So in this example, what we're trying to do is take a name,
give it to a new user, and then add that new user to our database.
And that's pretty much what's happening in both.
In the first one, we have our SQL statement, our raw SQL query, of insert
into the table User, name, with the value of name.
In the second one, it's pass a name to create a new user,
and then we're going to add that new user.
And then an important step is commit.
Commit is an important step that you can't forget for insert
and remove statements, because those are editing the database itself.
And for those statements, you need the commit
to let it know that this is a permanent change that I'm trying to make.
Similarly, if we wanted to implement a select statement,
we can use user.query.order_by(user.id).all.
So what does that mean?
So we are looking at our table User.
Inside of User, we want to query it.
And we're taking all of them, and we're organizing them by user ID.
And we're going to take all those users that we're selecting
and put them into Users.
So once we've switched to Flask-SQLAlchemy, all we need to do now
is create our database.
The hard part's over.
And creating our database is going to be two steps.
First, we need to create our Heroku Postgres DATABASE_URL, that elusive
DATABASE_URL that I spoke about at the beginning,
that this application that I provide is looking for.
And so to generate this DATABASE_URL, we type in "heroku addons:create
heroku-postgresql:hobby-dev."
What does that mean?
Heroku add-ons are different tools that we can use to improve our web apps.
We're going to be using Heroku PostgreSQL.
And then that hobby dev is the plan we're on, and hobby dev's the free one.
So the next step, then, is to do heroku config into your Mac terminal,
and voila, it spits out your DATABASE_URL.
So Heroku now knows the DATABASE_URL.
We actually made the DATABASE_URL.
It's up in Heroku.
But if we wanted to run the application locally,
our local application has no way of knowing.
So to tell the local application what it is,
tell a local application where the DATABASE_URL is,
what we're going to do is create a .env file.
So type "touch.env."
Then, inside of Atom, you can edit the .env and make it look identical
to the one I provided, where you have export FLASK_APP equals application.py,
telling when we do Flask run, that we want Flask run to look
for application.py, not app.py or server.py or whatever.
FLASK_DEBUG equals 1, that sets another environment variable that
makes it easier for us to interpret Flask errors,
because we'll all make mistakes.
And then for export DATABASE_URL, that's where
we set the environment variable DATABASE_URL to tell our program where
the database is.
To load these environment variables to your Mac, type source .env.
Now we've created a DATABASE_URL, but in fact, we've actually not
created the database itself.
We've told our application where to go looking,
and we told it to go looking at Heroku to find this database.
And we set aside that space, but we actually
didn't put our database table in it.
So we want a way to look at our database, much like in CS50 IDE,
we were able to use phpLiteAdmin to visually inspect our SQLite tables.
So we're going to be downloading this app called Postico,
and there's a free trial available.
So go to that website, download Postico, and then once you open Postico,
it's actually really easy to use.
Go back to Terminal, copy that DATABASE_URL, open Postico,
and then with the DATABASE_URL copied to your clipboard, click New Favorite.
The fields should be automatically populated,
and then click Connect to connect to your database.
So right now, when we do that, we don't see any table named User.
That's because we haven't created the table User.
And that's what we're moving onto now.
So part four, taking the files from your Mac and pushing those up to Heroku.
So we've gone from CS50 IDE to GitHub, from GitHub to your Mac,
now we're going from your Mac to Heroku.
So this statement might seem familiar.
We're going to do a pip freeze requirements.txt to update
our requirements file, though it shouldn't have changed in this
walkthrough, but it's a good habit to get--
it shouldn't have changed in this walkthrough,
but it's a good habit to get into.
Then we're going to do git add to load our files
and get them ready to send off.
We're going to get git commit, with our seal of approval
that we're ready to send these files to Heroku.
And then we're going to do git push heroku master
to send them on their way.
Now it's time to actually create the table for our database.
And to do so, type in in your Mac terminal
"heroku run python," which basically creates a read eval print
loop in Heroku for Python.
And once we're in there, then we can make some changes.
So what we're going to do is type in "from application import db."
We're going to do db.create_all, and then exit to get out of it.
And what this does is goes through our application.py
file, look for those classes that we define with the db.models,
and once it finds those classes and those columns that we set up,
it's just going to create that table for us.
So this step's actually pretty easy.
So if you press Refresh in the upper right hand corner of the Postico
application, you should now see a User table
appear, because we've successfully created our database table.
All right.
We're getting close.
Running locally-- so to run our web app locally on our own machine,
we need to first load the environment variables, and then type "flask run."
And remember, make sure your virtual environment
is activated by source bin slash activate.
Then we do source .env to load the environment variables,
and then flask run.
All right, this is where it gets cool.
Then on Safari or Chrome, go to localhost:5000,
and you should see your web app running.
Pretty cool.
But now, here we are--
part five.
It has been a long journey.
To see our Flask app on the web, run heroku open,
and you should see your web app running on the internet.
You can share the URL with friends and family.
Notice that if you add names to the web app, either locally
or on the internet, the database updates in Postico.
For this seminar, we took our little Flask app running in CS50 IDE,
and we, in step one, brought it from the CS50 IDE to GitHub.
In step two, we took it from GitHub to our Mac.
In step three, we switched out our SQLite database
for a Heroku Postgres one.
In step four, we took it from our Mac to Heroku.
And in step five, we took it from Heroku to the web.
Be sure to check out the sample code and the walkthrough
that I posted online to accompany this seminar.
My name is Carter Page, and this is CS50 seminar, Publishing Your Flask
App to the Web.
Thank you.