Webpages with Flask
Goal
Explore different functionalities of Flask with a simple dataset.
Table of Contents
Setup
Create a folder FlaskLab in COURSES as you usually do.
Then download flask_lab_app.py and Pokemon.csv and place them in that folder.
Getting Started
As you know from the reading, Flask is a web framework that lets you build dynamic a dynamic website using Python. You’re going to build a very simple app that grabs data from a file and displays it on dynamically-built (and ugly) web pages.
- The starter code starts with the Flask boilerplate and loads in the Pokemon data for you.
- Note that there is already a
homepage()function that is called when a user first goes to your website using@app.route('/')(feel free to make the string returned more exciting):@app.route('/') def homepage(): return "hello, this is the homepage" - Open up the Terminal in VSCode and run your python script as you normally would:
python flask_lab_app.pyYou should see something like:
* Serving Flask app 'app' (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: off * Running on http://127.0.0.1:5100/ (Press CTRL+C to quit)And if you the click on the link http://127.0.0.1:5100/, a web browser should open and you should see your message. Congrats, you made a website with Flask!
Outputting Data
The main goal of using Flask is that we are able to display data from your dataset onto your website. Normally we would have this data in a special location called a database, but we’ll just stick with loading from a file.
-
I’ve provided you with a dataset about Pokemon already in the repository, called
Pokemon.csv, along with aload_datafunction that handles reading that data into a list of lists - Now there are a lot of choices for how to display this data. If you wanted to let the user get a particular cell of your dataset, you could make the decorator for the function include the desired row and column as variables:
@app.route('/<int:row>/<int:column>/')The
<>indicate that the string inside them should be a variable that is passed to your associated function, and in this case we are also convertingrowandcolumntoints immediately. The function has to take those exact arguments, like so:def get_cell(row, column):Use those two snippets to complete the
get_cellfunction so that you can go to the pageyour_url/0/1and see a page withNameon it. - Now try letting the user get an entire row of the dataset, perhaps by specifying the Pokemon name that they want. Remember that you can use additional
/in your routes to specify different commands, such as/name/<pokemon_name>.
Handling user errors (and your own)
You may have noticed as you were doing the previous pieces that it would be nice if you could have errors display nicely. Fun fact, you can!
- Add a function with the decorator
@app.errorhandler(404)to catch page not found errors. The function will need to take an argument (which is the error):@app.errorhandler(404) def page_not_found(e): return "sorry, wrong format, do this instead...."Make sure that the function lets the user know what format they should use for the URL to get the information they want, perhaps with some examples.
- You can add a function for internal server errors as well, i.e. when you have a bug in your Python code:
@app.errorhandler(500) def python_bug(e): return "Eek, a Caterpie!"
Submission
Submit your Flask app at this point for an extra engagement credit. Then play around and make more functionality for your website!
HTML
You may already be aware that website use HTML (and CSS) to specify how they should look (and be less ugly). You can do that with Flask via the following:
- Create a
templatesfolder in your lab folder - Create a file in that folder
index.htmland put in the following boilerplate:<html> <head> </head> <body> </body> </html> - Within the
headingput in a set oftitleHTML tags and place a placeholder{{title}}between them (this language is called Jinja and it’s a lot like Python):<title>{{title}}</title> - If you have as many tabs open as I do regularly, you can’t actual see the titles easily, so, within the
body, put in a heading with the title as well:<h1>Welcome to the {{title}}!</h1> - Now you need to go edit your existing Flask app to use your new template. Open
flask_lab_app.pyand edit yourhomepage()function so that instead of just returning a plain string, it returns the result of callingrender_templatewith your title of choice:@app.route('/') def index(): return render_template('index.html', title="Pokemon rule!") - Run your app and check out your new fancy (kind of) homepage!
Data with Templates
Even though you don’t strictly have to use Jinja, it makes displaying lists much easier. Let’s display the headings of the Pokemon dataset on the homepage.
- Within
index.htmlmake an unordered list in thebody:<ul> </ul> - Within that unordered list, we’ll use Jinja to make a list item for each heading in our list
headings:{% for heading in headings: %} <li>{{ heading }}</li> {% endfor %} - Now we need to actually pass that argument. Within
flask_lab_app.py, add to the arguments that you are passing torender_templateinindex:def homepage(): return render_template('index.html', title="Pokemon rule!", headings = data[0]) - Restart your app to see your new fancy list!
- Try adding another list of the first data row of the Pokemon dataset.
Fun extra
By combining the route variables and Jinja placeholders, you can let the user display what they want on your page.
Try making a new template and route so that you can go to your_url/greeting/your_name and find a web page that greets whatever the user puts for your_name.