<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. * 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. --- ## Simple Calculator: Flask App * Write a Flask application with a two web pages: * The first page should get the information from the user: * Ask the user to enter 2 numbers and a symbol. For example `3 + 4` or `7 * 8`. * The second page should display the result of the calculation. --- ## 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 Simple Calculator application so that the user can press "Calculate" and be taken to the next web page displaying the result. --- ## 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 which numbers and symbols the user entered. * Calculate the result. * And send the updated HTML. <br> ### How do we do this? --- ## 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'] ``` --- # Project Starter Code Now go take a look at your project starter code. Does it make sense? Do you have any questions about it? --- ## 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) --- ## Limitations So Far * At this point we can only view the data that is submitted through the current form. * For example: * what if we wanted to save and display all the calculations the user has made on our calculator? * what if we wanted to save and display (or analyse data about) all the calculations anyone has ever made on our calculator? * We will learn how to do this in our next 2 topics: * Cookies * Saving Files on the Server --- ## Global Variables * A way to store this data. * Opens our code up to lots more errors. * A stepping-stone to using Cookies and Files. * MUST NOT BE SUBMITTED IN ANY COMP1010 WORK. (If you get global variables working, but can't transition them to Cookies or Files, please ask your tutor or myself for help.) --- ## 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 | --- ## 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/) ---
{"metaMigratedAt":"2023-06-16T20:56:30.992Z","metaMigratedFrom":"YAML","title":"5.3 Web Apps Servers and Flask","breaks":true,"description":"Previously on COMP1010:","contributors":"[{\"id\":\"969c3c3d-0ef4-4f08-b22a-2f2b8951224b\",\"add\":13100,\"del\":13100}]","slideOptions":"{\"transition\":\"slide\"}"}
    1189 views