你好, Flask
Learning Goals
- Build a simple flask app to gain an understanding of how to use this framework
- Become familiar with Jinja, a templating language used with Flask

背景
Flask, a microframework used for web development, can be confusing when starting out. There are multiple files of different types, and they must reside in specific folders. In this problem, we’ll start with the absolute minimum—a single Python file. From there we will move on to create your first full-fledged web app!
入门
- Log into cs50.dev using your GitHub account.
- Click inside the terminal window and execute
cd. - Execute
wget https://cdn.cs50.net/2022/fall/实验s/9/helloflask.zipfollowed by Enter in order to 下载 a zip calledhelloflask.zipin your codespace. Take care not to overlook the space betweenwgetand the following URL, or any other character for that matter! - Now execute
unzip helloflask.zipto create 的文件夹中名为helloflask. - You 不再 need the ZIP file, so you can execute
rm helloflask.zipand respond with “y” followed by Enter at the prompt.
实现细节
The most simple Flask app uses just one file, app.py. This will 创建一个n html page and say 你好. Add the following into app.py to get started.
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "你好,世界!"
This bit of code starts by importing Flask from the flask library. Though we don’t need to get too far into the weeds here, Flask is what programmers call a “class”. Suffice to say for now, it’s like a template 的 application we’ll be building. The line app = Flask(__name__) tells Python to 创建一个 particular app, henceforth called “app”, from the template. To create the particular application, we give the Flask class the名字 of the current Python file (represented by __name__), which allows our application 查找 other files we might later add to it. In this case, the名字 of the file is also “app” for consistency.
The most mysterious line in the application you’ve written is probably the one where you wrote:
@app.route("/")
This kind of function is called a decorator. Decorators allow you to take a basic function, like app.route, and extend its functionality with something custom: the function you 编写一个fter the decorator. You can 阅读 更多 关于 decorators if you want, or you can just keep using them for now.
This line tells Flask that if an HTTP request comes in for “/”, the index function should be run.请注意,, if we renamed the function to be homepage, this line would tell Flask that—every时间 it receives an HTTP request for “/”—it should run the homepage function.
注意 the index function returns a piece of text, “你好, 世界!”. This text is what Flask will render to the user when their request to the “/” route is complete. The returned text could be (and often is!) the text of an entire HTML file, which the browser then renders accordingly. But it’s just a piece of text for now, for brevity’s sake.
To run your app, type flask run into the terminal, and you will get a link to click, similar to when you run http-server. You’ve written a Flask app! Try returning different text, like <h1>你好,世界!</h1>. How does this change what you see?
Templates
Instead of putting HTML code right into our Python programs, it’s best to move our HTML into separate files, to keep separate concerns separate. Since our app will likely include a number of similar HTML files, we can create one layout.html file which all our HTML files “extend”. “Extending” an HTML file 意思s to keep all of the content of that HTML file while also adding some custom content, specific to a particular page.
By convention, Flask puts all HTML files inside of a templates folder. Inside the helloflask folder, make 的文件夹中名为 templates using mkdir templates. All your HTML files will go in this templates folder.
Inside templates, 创建一个 layout.html file that looks like this:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello, Flask</title>
</head>
<body>
<h1>Hello, Flask</h1>
{% block body %}{% endblock %}
</body>
</html>
The {% block body %}{% endblock %} syntax comes from Jinja, which is a “template engine” for Python. The line with {% block body %}{% endblock %} is what makes this a layout file. If another HTML file extends layout.html and defines a block called “body”, we’ll insert that block into this 小组课 of the layout.html. 一份 layout file can contain as many blocks as you want. Just give each one a different名字。
Now create index.html so that it extends the template layout.html, like this:
{% extends "layout.html" %}
{% block body %}
<p>Next we'll put a form here and get some POST action!</p>
{% endblock %}
Finally, we’ll go 返回 to app.py to see these changes come to life. In the initial import, we’ll need a few 更多 functions from Flask (as shown below). Then, replace the direct return of text with a call to Flask’s render_template function. The purpose of the render_template function is to preprocess index.html such that, when we give it to the browser, it also includes the HTML it “inherits” from layout.html.
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html")
When you run your application now (type flask run!), you’ll get a little 更多 out of your app. But it isn’t really interactive yet!
Forms
HTML forms allow the user to enter data into input fields and send the data to the server, often using the POST method of the HTTP protocol. You can learn 更多 关于 HTML Forms here.
Add a form to index.html so that it looks like this:
{% extends "layout.html" %}
{% block body %}
<form action="/" method="post">
What is your favorite color?
<select name="color">
<option value="red">Harvard Crimson</option>
<option value="blue">Yale Blue</option>
</select>
<button type="submit">Submit</button>
</form>
{% endblock %}
笔记 that each form element has both a 姓名 and a value. The名字 an element is what we’ll use to refer to that element. Its value is the value submitted by the form. Each get passed into app.py for our use when the form is submitted.
Run your app, visit the / route, and 提交 the form. Oops! 你应该 see the message “Method not allowed”. So we’ll first need to make sure Flask allows the use of the POST method on /.
POST
In app.py, we need to adjust our route to handle the POST request. Here is what our new app.py looks like.
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route("/", methods=["GET", "POST"])
def index():
if request.method == "GET":
return render_template("index.html")
else:
print("Form submitted!")
color = request.form.get("color")
return render_template("color.html", color=color)
This例子has some logic in it: if the user submits a GET request, we’ll show them the basic index.html with a form to 提交. If, though, they 提交 a POST request, we’ll do a few different things:
-
print“Form submitted!” to the terminal, for debugging’s sake. 我们应该 later remove this once we’re satisfied our program works as intended. - Store the value of the “color” input in a variable also called
color, as viacolor = request.form.get("color"). - Render a new HTML file,
color.html, and pass the value of thecolorvariable into the file under the very same名字,color.
Let’s create color.html for our application to work:
{% extends "layout.html" %}
{% block body %}
<p style="color: {{ color }}">Your favorite color is {{ color }}.</p>
{% endblock %}
Notice how we can insert the value of color anywhere in our HTML we’d like—whether as text in a sentence, or as a placeholder 的 value of some CSS property.
We’ll likely want to add some additional input validation, however, instead of simply trusting our users to send only the values “blue” or “red” via POST. What additional code could you add to ensure the colors we receive are valid colors?
如何测试 Your Code
你的程序应该 behave as per the例子above.
No check50 for this one!
如何提交
No need to 提交. This is a 练习题!
Adapted from 27 Classrooms, by Mark Sobkowicz, Lincoln Sudbury Regional High School