Lab 8: Introduction to
Web Applications

Part 2: Computing with Flask

If you find typos or problems with the lab instructions, please let us know.

Ok, a web page that prints “Hello World” is not really very compelling. Let’s do something a bit more interesting.

In part 2 of the SPIS webapps tutorial, we’ll learn about how to:

  • Perform a calculation based on a parameter that’s in the url

  • Start building a larger multi-page web application

Part 2 is individual; each of you should do it separately, though you are allowed (in fact encouraged) to help one another if/when you are stuck.

Step 1: Fork your repl from Part 1 and update README.md

In part 1, you created a Hello World app. We are going to leave that one alone, since it's a record of your work for part 1, and it's also a useful starting place for many future things we might want to do.

It's handy to have a very simple web app around that you can use a starting point to try things.

So, fork that repl now. As a reminder, to fork a repl mean to create a copy of it (like a fork in the road). The drop down menu by the name of the repo reveals the fork button.

Then, edit your README.md file and add a new heading:

# Part 2

Under that, put your name, and your pair partner's name, and put a link to your new forked repl. For example:


# Part 2


Phill

Repl: https://replit.com/@phtcon/TragicHoarseCompilers-2


Aammya

Repl: https://replit.com/@aammya/HipsterJazzyJaguars-2

Step 2: In your fork, add an ftoc function to main.py

We’ve already seen a function that converts Fahrenheit to Celsius. Here it is again:

def ftoc(ftemp):

return (ftemp - 32.0) * (5.0 / 9.0)

Let’s add this to our main.py file, so that we have the following (new code shown in bold):

from flask import Flask

app = Flask(__name__)


@app.route("/")

def hello():

return "Hello World!"


def ftoc(ftemp):

return (ftemp - 32.0) * (5.0 / 9.0)


if __name__ == "__main__":

app.run(host='0.0.0.0')

Now, you can test your function by doing this:

  • Comment out the last line of code, and add a line underneath it with the single word pass. In Python, the keyword pass is used as a placeholder for an empty if block, or an empty function definition. This will temporarily keep the web app from loading. Be sure the lines are indented at the same level.

Before

After

  • With the app.run(host='0.0.0.0') commented out, click Run to load main.py.

  • In the Console window, type various function calls such as ftoc(212.0) and ftoc(32.0) in the Python Console

  • If your ftoc function works, uncomment the app.run(host='0.0.0.0') line, and remove the pass line (i.e. put the code back the way it was).

  • You are good to go to the next step where we connect this to the web app.

Step 3: Connect this to the web app

To make this code work with the web app, we need to add a few more lines of code. The new code is shown in bold below.

First, we’ll just do it and see what it does, then we’ll unpack each line of code and explain its purpose below.

from flask import Flask

app = Flask(__name__)


@app.route("/")

def hello():

return "Hello World!"


def ftoc(ftemp):

return (ftemp - 32.0) * (5.0 / 9.0)


@app.route('/ftoc/<ftemp_str>')

def convert_ftoc(ftemp_str):

ftemp = 0.0

try:

ftemp = float(ftemp_str)

ctemp = ftoc(ftemp)

return "In Fahrenheit: " + ftemp_str + " In Celsius " + str(ctemp)

except ValueError:

return "Sorry. Could not convert " + ftemp_str + " to a number"


if __name__ == "__main__":

app.run(host='0.0.0.0')

Before running this new code, we're going to want to open the mini Repl.it browser window in its own window, so that we can edit the URL to add parameters into it. To do this, copy the URL in the mini Repl.it browser window, open a new tab in your browser, and paste in the URL.

Alternatively, you can click the button labelled Open in a new tab as shown in the screenshot below; that will do the same thing.

After doing that, try running your new code again by clicking the Run button.

(Note: if your app it taking a long time to load in a new tab, try going back to the replit and running/stopping/running again; sometimes we've found that the page just never finishes loading, whereas other times it loads right away.)

You should now be able to put in URLs such as the ones below, where the last part is a Fahrenheit temperature you want to convert to Celsius:

Note: Make sure to replace the first part of these URLs (https://YOUR_URL) with your own URL that you copied and put into a new tab.

For example if your Repl.it is named quizzicaldearestdeveloper and your username is phillipconrad, then the URL will be https://quizzicaldearestdeveloper.phillipconrad.repl.co/

Try it and see what you get. Also try some URLs where the last part is not valid, e.g.

If you’ve gotten this far, you’ve gotten a great start.

Check in with your partner to make sure that both of you have succeeded up to this point.

Step 4: Understand how it works

One of the keys to understanding how Flask works is to focus first on these lines of code in main.py

@app.route('/')

@app.route('/ftoc/<ftemp_str>')

The parts of our code that start with the @ sign are called decorators. In this case, they come right before a function definition, and they tell Python to do something special with the function definition that follows.

In this case, the @app.route(path) decorator indicates that URLs that end in path should be routed to the function that follows.

In the path parameter of the app.route decorator, anything in angle brackets, such as <ftemp_str> stands for a value that is passed into the function as a parameter. These are always of type str (string) and therefore have to be converted if they are going to be used as something else (e.g. float, int, etc.).

Now try some things on your own.

Step 5: Now you try it!

Now, let's test your knowledge of what you've seen so far by seeing if you can extend this web app on your own. (This is still individual work, but you may consult with your pair partner if you need support.) If you run into any problems, (e.g. the dreaded "Internal Server Error" see the Troubleshooting section below

  1. Add a function that converts Celsius to Fahrenheit, i.e. def ctof(ctemp): that just like the ftoc function, is a “pure” function, i.e. it “doesn’t know its part of a web app”, and computes an answer only based on its parameters.

  2. Then, add a function with a decorator @app.route('/ctof/<ctemp_str>') that will convert the ctemp_str into a number, pass it into the function, and produce output. You can use the convert_ftoc function as an example to build on.

  3. Add a pure function that converts miles to kilometers, i.e. def miles_to_km(miles):

  4. Then, add a function with a decorator @app.route('/mtokm/<miles_str>') that will convert the miles_str into a number, pass it into the function, and produce output.

  5. If that works, then see if you can each write your own function (each pair partner)— any Python function of your choosing—and then add it to the web app. It could be a conversion, but it could be also anything that we can compute in Python.

    Note that if your parameters are numbers, you'll need to convert them from number to string first; but if they are strings, you can work with them directly (no need to convert).

    Note that you can use a route such as @app.route('some-route/<a>/<b>/<c>') if you wanted to have a function that took three inputs instead of just one.

    The function that handles that would look somet
    hing like this. Here we are just echoing the values to the web page, but it would be nice to do something more interesting, such as computing the total length, finding the longest or shortest of the three, etc.

Note: For your new changes to be rendered, you must close your server and then rerun it. You can use the Stop and Run buttons to stop and restart the server as needed.


Another Example

Here's another example of a custom function. Note that yours shouldn't be an exact copy of this one. Please try to come up with something else. (You may use functions you already studied elsewhere during SPIS though; the idea is to learn how to use a web app to provide into to the function, and display the result.)

The pure function. It takes three strings a, b, c as parameters, puts them in a list, sorts the list, then returns it.

The handler for the web request. Note that since the parameters a, b, and c are assumed to be strings, we don't have to do any conversion. We only have to convert the resulting list to a string (via str(result)) so that we can return it

An example call to the function:

Troubleshooting

If you get the Internal Server Error, like this, don't panic! What to do is explained below.

This means something went wrong in your app, and typically if you look in the Console window, you'll see what. For example, suppose we have this function, which has an error in it. (Can you spot the error? Spoiler alert: Repl has underlined it with a wavy red line)

When we run this, we get Internal Server Error. But we also get this output in the Console window. It's a bit of a scavenger hunt, but if you read slowly and carefully, eventually you find the helpful part. We zoom in on this in the image below.

Fix the error, and the Internal Server Error goes away!

In general, this is how you'll find and fix errors in your web app.

What have we shown here?

The important thing I want you to take away is that, at this point, we have a way to:

  • Take anything you can do in Python with a function

  • Convert that into a web app that anyone in the world can use to run your function

That's pretty cool. You can take your Python coding, and expose it to a global audience.

Now, granted, there's still long ways to go between this, and professional looking web apps:

  • The user interface isn't great: we'd like to be able to prompt users for input with nice forms, instead of asking them to type numbers into a URL

  • The output isn't great either: so far, it's just plain looking text.

  • We haven't talked about security yet: if you wanted to have only some people have access to your app, and not others, or if different users should have different roles (e.g. mentees, mentors, instructors). That is still to come.

  • We also haven't talked about data storage yet: if you want to upload some information into your web app and have it remember that so you can come back to it later? That's still tbd.

But, the important thing is that you have a way to take your Python coding, and share it with the world. I hope that gives you some motivation to keep going!

Step 6: Update your lab08-name1-name2 README.md file

Now, let's go back to the GitHub repo in the spis2022 organization called lab08-name1-name2 where you created the README.md file.

Previously you added a section with this information (i.e. a link to the repls for part 2 for each of the pair partners. (If you didn't do this before, do it now.)

# Part 2
Phill

Repl: https://replit.com/@phtcon/TragicHoarseCompilers-2


Aammya

Repl: https://replit.com/@aammya/HipsterJazzyJaguars-2


Now add links for the running web apps for each of the members of your pair. (You can review the instructions for Step 4 of Part 1) if you need a refresher.

In addition, include a description of the custom function you wrote in Step 5, and the URL used to access it.

For example, supposed you wrote a function that determines which string is longer between two strings, def longer_string(string1, string2), and you implemented that using a web address /longer_string/string1/string2, you'd write something like in your README.md file. The link should be clickable when you save the README, and should execute your function.

My custom function is named longer_string and it is available at the web address:

https://mydearestdeveloper.phillconrad.repl.co/longer/short/much_much_longer

Also include links to tests of the ftoc, ctof, and mtokm functions, such as these:

ftoc test: https://mydearestdeveloper.phillconrad.repl.co/ftoc/212
ctof
test: https://mydearestdeveloper.phillconrad.repl.co/ctof/20
mtokm test: https://mydearestdeveloper.phillconrad.repl.co/mtokm/143

Each of the links should do the appropriate conversion when you access them.

This step is important, because it's how the mentors can get access to your work to give you feedback.

Step 7: Learning about HTML and CSS

Our next steps will be to learn a bit about:

  • HTML and CSS, the languages we use to make our web pages look like “real web pages” instead of just plain text.

  • Both of those are for our next lesson, but we can at least get a head start if you’ve finished this material early.

So, at the moment, the values we are returning from our functions are plain text that shows up in the browser. That’s fine for getting started, but eventually we’d like something that looks like a “real web page”. For that, we’ll need to learn a little bit about HTML and CSS.

If you have not worked with HTML/CSS before

  • Get started on learning HTML and CSS now using one of the best free resources on the web, the site: w3schools

We suggest you do the following:

  • Visit the HTML tutorial and read/skim over the first seven lessons

  • After learning some HTML, learn a bit of CSS by reading over the first four lessons of the CSS tutorial

  • After each lesson check in with your pair partner to make sure both of you are understanding the content.

Side note: the Python tutorial is also "not bad" as a quick reference / review.

If you and your partner want to learn more about HTML/CSS (or Python) you can spend more time on the website.

Step 8: Check in with your pair

Up until now, we've been working individually to make sure that each member of the pair or trio has the basic mechanics down.

In the next part of the lab, there is about to be a deeper dive into webapps content.

Begin working with your partner together for the rest of the lab and before continuing, make sure that both of you have a solid understanding of the beginning content of this lab. After both of you feel that you have a good understanding of the beginning content of the lab, continue through the rest of the lab, making sure both of you have a good understanding of the material.

Then, move on to Part 3: Templates