Topic 9: Flask Applications - University Of Western Australia

Transcription

Topic 9: Flask ApplicationsCITS3403 Agile Web DevelopmentAdapted from the Flask Mega-Tutorial, by Miguel flask-mega-tutorialSemester 1, 2022

Full Stack Development? Full stack development refers to developing all parts of a webapplication: database, web server, application logic and front end. There are various “Full stacks” people use to develop:– LAMP (Linux, Apache, MySQL and PHP)– Ruby on Rails– Django (Python) We’re going to use a number of tools in this unit:– Flask: is a micro framework, that allows us to write our backendin Python. It contains its own lightweight webserver fordevelopment– SQLite: is a lightweight database management system– AJAX and JQuery: We have already seen these. We will usethese for making responsive web pages.

Full-stack development Fullstack development refers to developing everypart of the web application. It involves knowing all the technologies used frommobile and front end, (HTML, CSS, javascriptframeworks) though to the backend logic, securityand database models used at the backend. Most developers are specialised in one part of thestack.

Development environmentllllA lot of web development is done from the command line,since traditionally servers didn’t need a graphical front end.We can use Git to develop on laptops and push code to theserver, but we still rely heavily on command line tools.By now, every one should have a good text editor that doessyntax highlighting etc, some tool to allow them to compileor run code with the command line, and a browser withdeveloper tools to view source, and debug javascript.You should also have a Git client to regularly commit yourcode, and push to others.

Getting started with Flask Flask is a micro-framework to run on theserver, but it will run on any machine, andhas few dependencies. You will require python3 installed in youroperating environment, with pip. Use pip to install venv (virtual environment)first and initialise the environment. Now install Flask. Any required modules willbe preserved by the virtual-environment. You can now run flask by typing flask run,but the app doesn’t know what to run. Write the following into app.py, run theprogram again. Use a browser to see your app in action!(http://localhost:5000)

Application structure Our app.py file doesn’t look likemuch. It has a method to return ‘Helloworld!’ that is decorated with@app.route(‘/’). app is an instance of the classFlask. When it runs it listens forrequests, and if the route matches adecorator, it executes thecorresponding function. A requestobject is passed to the method. The return of the function becomesthe response. But this structure doesn’t scale well.

A better application structure A better structure is to create a package appthat will contain all the code we need for theweb app. It has an init .py file to create aninstance of the Flask class. We can create a file routes.py, to containthe request handlers. Finally, we need a file at the top level toimport the app. We set the system variableFLASK APP to the name of this file, so flaskknows what to run. Now the app package can contain files forhandling routes, modules, templates, testsand anything else our application requires.

Server-side vs Client Side Rendering There are two approaches to servingdynamic HTML: The server can build the HTML when itreceives the request and send to client. The server can send JS and an HTMLskeleton to the client, and the client canthen request JSON and build the HTMLusing AJAX and JQuery. Server Side Rendering is the traditionalapproach. Client Side Rendering is more flexible andallows greater support for non-browserdevices. Flask supports both forms very well.

Client Side Rendering For client side rendering, the client firstneeds to access a HTML template andsome JS. Flask projects have a static directory toserve non-dynamic files, including HTML,CSS, JS and images. We can then have flask redirect allrequests for a file to the static html wewant to serve. We now need HTML and JS for the client

HTML and JS for the Client

HTML and JS for the Client

And routes to service the AJAX requesthttps://drtnf.net/static/wordle.html

Server-side Rendering Our app will now listen for requests, and wecan use python functions to build html pagesto return as a response. However, this mixes the logic and thepresentation. A typical pattern to use is to have atemplate or views directory to have somehtml that references objects and code, and arendering function that will take a templateand some data and builds the htmldynamically. Flask uses jinja for this task, but there aremany alternatives (pug, handlebars,typescript)

Using Jinja We separate presentation and logicby having a template directory tocontain annotated html, and specify arending function in the routes.py file When a request is received flask willlook for the matching template (in thedirectory templates) and convert thetemplate to pure html using namedvariables in the function. Two {{curly braces}} are used todistinguish html from pythonvariables, and jinja does thesubstitution

Jinja Loops and Conditionals Depending on the parameterspassed, we may want to displaythe data differently. Jinja provides loops andconditionals to allow the displayto adapt to data. For example, it is common topass in an array of objects, andthen present them in a table. Or we may want the display tovary depending on who islogged in.

Jinja Control Statements The syntax for control statements is touse {% braces %}. Conditionals use if, else, elif, aswell as endif, since whitespacescoping doesn’t work for html. We can also use for and while loops foriterating through collections.

Jinja Inheritance Since we often want the titles, menus,footers in an application to be the same,we can have the templates inherit fromeach other. The block xxxx is left unspecified forother templates to fill in, and they canextend the ase template by justspecifying how they would fill in xxxxlThis principle isrefered to as DRY:dont repeat yourself

Forms To build PUT requests,we typically use forms.Flask uses theWTForms module tovalidate Post Requests Install flask-wtf withpip and create a newfile in app, forms.py There are three parts tothe form: the form class,the template containingthe form, and the routefor processing the form.Flask apps should have a secret keyto protect against cross site requestforgery (CSRF). You can set inapp.py, but there are better ways.

Rendering Forms Jinja works with flask-wtf to putthe appropriate input elementsin the page. The form.hidden tag() is usedto protect against CSRF attacks The form elements are definedby the forms.py class Attributes can be appended tothe elements in brackets. If a form doesn’t validate, theerrors are accessible in a list,but are rendered server side.Faster client side validation canbe applied using javascript. The url for()maps back from thefunction name to the route.

Processing Forms To process a form, we configure aroute for the POST method. We define an instance of the formclass, for both rendering and wrappingposted data. A GET request won’t validate, so it willjump to the last line, and render thepage. If a POST request validates, a flashmessage is created, and the page isredirected to the index. The flash messages are just a list thatcan be accessed by other pages. To actually check a users passwords,we need a database (next lecture).

App Configuration Storing the secret key in a source file isn’ta good idea. Secret keys and usercredentials should always be manuallyconfigured, and never part of therepository. Setting them as systemvariables is a good approach. Create a configuration file to store allconfiguration variables. This can then beloaded when the app runs. The environment variables can also storedatabase locations and credentials, andkeys for third party services

Debugging and the Flask Shell The Flask shell is a usefulway to test small functionsand their integration withflask, without using abrowser. It loads the flask app, and allthe dependencies, butdoesn’t need the serverrunning. You can set theshell context to havevariables predefined whenyou start the shell. Debug mode is also veryuseful. Set the systemvariable FLASK DEBUG 1to get a trace of the errorswhen the server crashes.

Suggested ReadingRead “What is Code” by Paul ord-what-is-code/

web app. It has an _init_.py file to create an instance of the Flask class. We can create a file routes.py, to contain the request handlers. Finally, we need a file at the top level to import the app. We set the system variable FLASK_APP to the name of this file, so flask knows what to run. Now the apppackage can contain files for