This is a commentary on Python's Flask Quickstart guide. Here's all the context I wish I knew when building the most basic of Flask apps.
The Quickstart Code
Fire up a terminal. Create a new folder for us to play in.
mkdir flask_demo
cd flask_demo
We're going to need to have flask
installed. Feel free to do it in a virtual environment if you prefer and know what that means. Otherwise, do a quick
sudo pip install flask
And if you don't use pip then, as they say, where there's a will, there's a way.
Use your favorite editor to create and edit the file app.py
. I'll be using vim.
vi app.py
Let's write a bare-bones "hello world" app. (Yes, if you haven't done this before, you should type it out rather than copy and paste.)
from flask import Flask
app = Flask('flask_demo')
@app.route('/')
def hello_world():
return "Hello world!"
if __name__ == '__main__':
app.run()
Congratz, you wrote an app! Now let's walk through what you just did.
The import
from flask import Flask
This is a straight forward import in python - from the module flask
, import the the main interface to our microframework of choice that manifests as the object Flask
.
The App
app = Flask('flask_demo')
By calling our class Flask
, we create an instance it. The first argument defaults to app name, which we passed 'flask_demo'
to. The instantiated object is saved into variable app
.
A Route
@app.route('/')
def hello_world():
return "Hello world!"
Now we're getting into what web is. To keep the focus of this discussion to only what we need, think of a web site as two parts for now: the core address and the directory within that site.
Compare the following two addresses as an example:
They both take you to the same web site (http://www.thegrimmscientist.com), but to two different places within - one at what we can call the root, the other to a page deeper within the site. For now, just know that the @app.route('/')
is saying "hey, the function that follows me is what you should call to decide what to return when someone accesses the root of your site."
It follows that you should expect to see "Hello world!" whenever you ping the root of whatever site we eventually deploy this app to.
Make it Run-able
We defined the app itself and gave it a route to hit. All that's left for us is to let calling this script directly deploy this app as locally.
if __name__ == '__main__':
app.run()
All we really need is app.run()
, but burying it inside of that conditional is the pythonic way of saying "Do all that follows only if you called this file directly." Which is to say: if you find yourself wanting to deploy the service from something else and import that beautiful view (the route-decorated function from above), you won't get a gnarly error by having your imports try to deploy the app before your other thing also tries to deploy the app.
Hey, you wrote a thing! Save it. Exit.
Deploy
Back in your terminal, you should still be in the same place as the app.py
file you just made.
python app.py
This tells python to run the given file. When I run the above command, my terminal prints out:
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
What we really care about is the http://127.0.0.1:5000/
. There are a few pieces here, and it's all very important.
http
is the protocol we're using. Most of note: you're not using https
. Yes, you're probably using http
and https
for most (all?) of your every-day web browsing. Yes, it is magic powered by a series of tubes full of cats.
127.0.0.1
is an ip address - a very special one. It is the reserved address pointing back to the computer you're currently working on. It can alternatively be written as localhost
. i.e., http://127.0.0.1:5000/
is the same as http://localhost:5000/
.
5000
is a port. This is obscured during normal web browsing, but absolutely has to be understood when you start playing with deploying your own stuff.
The short version is that when you talk to a server, you always talk to it through a port. It lets you talk to different services on the same server by talking to different ports where each service can have distinctly different behavior. Many services have default ports and you can stick to the default ports if you want. Real-world web sites use port 80 by default. When you came to www.thegrimmscientist.com, the interwebs looked up an ip that is matched with that web site and sent you to port 80 on whatever's at that ip. It turns out the computer at that ip has a server running and listening for requests at that same port 80. The server decides to fulfill your request for the contents of this here blog.
Except for us, our server says its running at port 5000
; not 80
. And that's intentional. If you're deploying your app this way (rather than, say, using Gunicorn and Nginx), it's assumed it's for dev. Port 80
is meant for production.
Navigate to Your App
In your browser, navigate to the http://127.0.0.1:5000/
from earlier. Be sure to copy that whole address, including the port.
Do you see "Hello world!
" as the web page? Congratz! You're now talking to yourself, web style.
Educational Modifications
I now advise you to start playing with your app and seeing how the changes manifest in your browser.
Change the port
Remember that little line we used to actually run the app we made? - the app.run()
? That's where it decides what port to run on (defaults to 5000
), and where we can deviate from default. Add the parameter port=5001
.
Shut down your current sever and start it again after you make that change. You should see the different port number logged to console at server start. Navigate to the now-different-port in your browser. Try to navigate to the old port.
Add Another Route
Second, add a second route. Replace the
@app.route('/')
def hello_world():
return "Hello world!"
from earlier with the first example in the Routing part of the quickstart guide:
@app.route('/')
def index():
return 'Index Page'
@app.route('/hello')
def hello():
return 'Hello over here`
Save. Restart your server.
At your site root (localhost:5001
, or whatever port you're using now), you should now see Index Page
instead of Hello World!
. You should also be able to navigate to the /hello
page - localhost:5001/hello
- and see the new "hello" text.
Happy Flask-ing!