<style>
.reveal {
font-size: 27px;
}
.reveal div.para {
text-align: left;
}
.reveal ul {
display: block;
}
.reveal ol {
display: block;
}
img[alt=drawing] { width: 200px; }
</style>
# COMP1010
## 5 Web Application Development
### 5.3 Web Servers and Flask
---
## Recap
* Previously on COMP1010:
* 5.0 Overview: we discussed the role of web browsers and web servers in running a web application.
* 5.1 HTML: we learnt how to write HTML to create a web page.
* 5.2 PyHTML: we learnt how to create HTML quickly and accurately using PyHTML.
* But:
* Our forms don't do anything.
* We can't go from one web page to another.
---
## Warning - It Might Seem Like a Lot
* This lecture looks like it has a lot of information.
* It might seem overwhelming at first.
<br>
### BUT...
* After this lecture, you will be able to copy-paste generic Flask server code and (because you understand what each line means) make the appropriate changes to make your application run.
* So don't worry about being able to write any of this from scratch. Just understand what it does so you can adapt it to your own project.
---
## Generic Flask Application Code
```{python}
from flask import Flask, request
from pyhtml import html # TODO add imports
app = Flask(__name__)
@app.route('/', methods=["GET", "POST"])
def homepage():
if request.method == 'POST':
# TODO you received form data, handle it
# (usually produce HTML)
else:
# TODO you didn't receive form data
# (usually produce HTML)
response = html(
# TODO put your pyhtml code here
)
return str(response)
if __name__ == "__main__":
app.run(debug=True)
```
---
## Your Goal
* Your goal in this lecture, is to learn to understand the different parts of this code so that you can copy and paste it and then:
* insert your own code instead of the TODOs (mostly pyhtml to produce the content specific to your application)
* add more routes and functions (by copying the one already there and adjusting it to work for your application)
---
## Let's start from the beginning...
---
## Flask: A Simplest Application
```{python}
from flask import Flask
app = Flask(__name__)
@app.route('/')
def homepage():
return "Hello World!"
if __name__ == "__main__":
app.run(debug=True)
```
---
## Understanding the Application
### Things we already know:
* Checking if this file is the one to run before doing anything: (covered in topic 4)
```{python}
if __name__ == "__main__":
```
* A function which returns "Hello World!" (Which can be interpretted as a very simple web page) (covered in topic 3.2.5)
```{python}
def homepage():
return "Hello World!"
```
---
## Understanding the Application
### New things:
* importing Flask (still quite familiar)
```{python}
from flask import Flask
```
* creating a Flask object
```{python}
app = Flask(__name__)
```
* running the Flask object
```{python}
app.run(debug=True)
```
These allow us to use the Flask framework to do a lot of "behind the scenes" work.
---
## Understanding the Application: Routes
* To fully understand the line `@app.route('/')` we need to add a few more **routes**.
* Each route is associated with a function. (It needs be to created in the line above the function it is associated with.)
```{python}
from flask import Flask
app = Flask(__name__)
@app.route('/')
def homepage():
return "Hello World!"
@app.route('/another_route')
def some_other_function():
return "This is the webpage associated "+ \
"with <code>another_route</code>."
@app.route('/list_desserts')
def desserts():
return "Cake, Popcorn, Brownies"
if __name__ == "__main__":
app.run(debug=True)
```
---
## Flask: A Simplest Application
* Now have a read through the code and check you understand each step
```{python}
# import Flask
from flask import Flask
# create the Flask app
app = Flask(__name__)
# declare a route and link it to a function
@app.route('/')
def homepage():
# return HTML from the function --> this will show up when that route is navigated to
return "Hello World!"
# if this file has been run, then run the Flask app
if __name__ == "__main__":
app.run(debug=True)
```
---
## Note: Simplest Application
* The examples above produce very simple HTML.
* I've done this because I want you to get familiar with the Flask elements without being overwhelmed by PyHTML.
* So let's take some time to write a more complex one.
---
## Guess My Number: Flask App
* Write a Flask application with a two web pages:
* The home page should:
* Display the start of a game, telling the user to pick a number between 1 and 100 and not share it, and that it will guess numbers and the user will have to tell it `H` for higher, `L` for lower or `C` for correct.
* Have a `Start Playing` button for the user to indicate that they have chosen their number and are ready to play.
* The game page should:
* Display a guess as to what the user's number is.
* Have an input text box to allow the user to enter H, L or C.
* Have a button to confirm when the user has entered their response.
* Nice to have: a drop down menu instead of a textbox so the user can't accidentally input a value other than the expected ones.
---
## HTTP Request Methods
* Now that we know how to create different web pages under different routes, we need to be able to move from one page to the next.
* Hypertext Transfer Protocol (HTTP) is designed to enable communications between clients and servers.
* A client (browser) sends an HTTP request to the server; then the server returns a response to the client. The response contains status information about the request and may also contain the requested content.
* The two most common HTTP Methods:
* GET
* POST
---
## HTTP Request Methods: GET and POST
* GET:
* Is used to request data.
* Should not be used when dealing with sensitive data.
* So far we have used GET requests (they are the default when HTTP methods aren't specified for a route) to sent a request (the url) to the server and return the HTML to display.
* POST:
* Is used to send data to a server to create/update a resource.
* An example of such data is the contents of a form which has been submitted.
* The data sent to the server with POST is stored in the request body of the HTTP request.
---
## Getting to the Next Webpage
### Step 1: Tell the form where to go.
* Forms:
```{python}
form(action="destination_route")(
# Other form elements
input_(type="submit", value="Go")
)
```
* In the code above, when the `submit` is clicked, it will go to the `destination_route` function.
---
## Getting to the Next Webpage
### Step 2: Check that the destination route can handle POST requests.
* The default request is GET, so until now we haven't had to specify anything to get a web page.
* When a function is executed as a result of a form being submitted, it needs to specify that it is able to receive POST requests.
---
* To enable only GET:
```{python}
@app.route('/destination_route')
```
Or
```{python}
@app.route('/destination_route', methods=["GET"])
```
* To enable both GET and POST:
```{python}
@app.route('/destination_route', methods=["GET", "POST"])
```
* To enable only POST:
```{python}
@app.route('/destination_route', methods=["POST"])
```
---
* Now update your Guess My Number application so that:
* when the user clicks `Start Playing` it goes from the home page to the game page.
* when the user confirms their input on the game page it goes to the game page.
---
## Getting to the Next Webpage
### Step 3: Extract the data from the HTTP request in the destination.
* Now when we go to the game page, we need to be able to find out whether the user specified `H`, `L` or `C` in response to our guess.
* Then we can make our next guess.
* And send the updated HTML.
<br>
### How do we do this?
---
### Keeping Track of Data
* Two types of data:
* User's response:
* `H`, `L` or `C`
* Sent to the server through a form.
* Other data needed:
* `range_high`, `range_low`, `guess`
* Lots of [options for different purposes](#Keeping-Track-of-Data-Within-the-Server)
* For today, we will send it to the user in [hidden fields](https://www.w3schools.com/tags/att_input_type_hidden.asp) in the form, so that when they submit the form, we get it back in the server.
---
## Getting to the Next Webpage
### Step 3: Extract the data from the HTTP request in the destination.
* Import request from Flask library.
```{python}
from flask import Flask, request
```
* If we accept both GET and POST requests, we need to check if it was a POST (before we try and access the contents of the form).
```{python}
if request.method == 'POST':
```
* Then we can access the details of what was in the form. For this, we need to know the `name` field of our form element.
```{python}
my_variable = request.form['field_name']
```
---
## Finishing Guess My Number MVP
* Add the following features to Guess My Number so that a full game can be played.
* Now when we go to the game page, we need to be able to find out whether the user specified `H`, `L` or `C` in response to our guess.
* Then we (the web server) can make our next guess.
* And send the updated HTML.
---
## HTTP Responses
* When we return HTML from our server, it's referred to as the HTTP response.
* Flask also includes some information in it for the web browser.
* HTTP status codes:
* 2XX: Success (usually 200, meaning OK)
* 4XX: Client Errors (often 404, meaning Not Found)
* 5XX: Server Errors
* A full list of HTTP status codes can be found [here](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes)
---
## Keeping Track of Data Within the Server
* Hidden field (not secure from being seen and changed by the user)
* Global variable (prevents our program from being stateless - more likely to have bugs in our code)
* Cookies (great. We will learn this next. But not secure. Can be removed by the user by clearing cookies.)
* File on our server (not great for speed with large data, otherwise good, will be covered in this course)
* Database (good. not covered in this course.)
* We also won't be covering security such as encryption in this course.
---
## Keeping Track of Data Within the Server
| | Hidden Fields | Global Variables | Cookies | File on Server | Database |
|---|:-:|:-:|:-:|:-:|:-:|
Viewable by user | Y | | | | |
Changeable by user | Y | | | | |
Deletable by user | Y | | Y | | |
Makes code more likely to have bugs (mistakes) | | Y |
Expire | | | Y |
Ease of implementation | Very Easy | Very Easy | Easy | Easy | Hard |
Will be taught in COMP1010 | Y | | Y | Y |
---
## References
* If you're interested in learning more and taking these skills further:
* [Flask Quick Start Tutorial](https://flask.palletsprojects.com/en/2.0.x/quickstart/)
* [Flask Tutorial](https://flask.palletsprojects.com/en/2.0.x/tutorial/)
* [More about different types of HTTP requests](https://www.w3schools.com/tags/ref_httpmethods.asp)
* [Someone else's articulation of why I believe global variables are evil. (And incidentally, an example of what can go wrong when producing HTML which using PyHTML would not allow to happen.)](http://swcarpentry.github.io/training-course/2012/11/claiming-a-topic-why-global-variables-are-a-bad-idea/)
---
# Feedback
## Lecture: 5.3 Web Apps - Flask
<iframe src="https://docs.google.com/forms/d/e/1FAIpQLSdVVDLLKPgq94xEP2PjHulbc_q-ZiR4pmY-9kb41IkVuh7-wg/viewform?embedded=true" width="640" height="400" frameborder="0" marginheight="0" marginwidth="0">Loading…</iframe>
---
# Feedback
## Lecture: 5.3 Web Apps - Flask
[https://forms.gle/Uod5Jpr7AJ2z7cHLA](https://forms.gle/Uod5Jpr7AJ2z7cHLA)

{"metaMigratedAt":"2023-06-16T11:42:17.765Z","metaMigratedFrom":"YAML","title":"5.3 Web Apps Servers and Flask","breaks":false,"slideOptions":"{\"transition\":\"slide\"}","contributors":"[{\"id\":\"969c3c3d-0ef4-4f08-b22a-2f2b8951224b\",\"add\":23240,\"del\":11171}]"}