Flask Request and Response
The core of a web application is "receiving requests and returning responses." This chapter comprehensively explains how to read request data and construct various types of responses in Flask.
All examples can be directly run and verified in the development server.
Request Object — request
Flask provides all request information through a global proxy object.requestAll request information is provided.
Although it is a "global" object, Flask internally uses thread isolation to ensure each request gets its own data.
Example
from flask import Flask, request
app = Flask(__name__)
@app.route("/debug")
def debug():
# Output various request information to help understand the request object
return f"""
<h1>Request Debugging Info</h1>
<ul>
<li>Method: {request.method}</li>
<li>Path: {request.path}</li>
<li>Full URL: {request.url}</li>
<li>Host: {request.host}</li>
<li>Client IP: {request.remote_addr}</li>
<li>User-Agent:{request.headers.get('User-Agent')}</li>
</ul>
"""
Visithttp://127.0.0.1:5000/debug?foo=barYou can see the detailed request information.

Get query parameters — request.args
In the URL?The parameters after it are called query parameters (Query String).
Usagerequest.argsReading it, it works like a dictionary:
Example
def search():
# request.args.get() safely gets the parameter, returns None when the key doesn't exist
keyword = request.args.get("keyword", "") # Get the query keyword
page = request.args.get("page", "1") # Get the page number, defaults to 1
return f"""
<h1>Search Results</h1>
<p>Keyword: {keyword}</p>
<p>Page: {page}</p>
"""
# Test: /search?keyword=flask&page=2
# Test: /search?keyword=EXAMPLE
Recommended.get()Use the method instead of direct subscript access.request.args["key"], because the latter throws an exception when the key does not exist.KeyError, resulting in a 400 error page.
Get form data — request.form
To handle form data submitted by POST requests, userequest.form:
Example
def register():
if request.method == "POST":
# Use the value of the name="username" field in the form
username = request.form.get("username", "")
password = request.form.get("password", "")
if not username or not password:
return "<h1>Error</h1><p>Username and password cannot be empty</p>", 400
return f"<h1>Registration successful</h1><p>Welcome {username} to EXAMPLE!</p>"
# Display registration form on GET request
return """
<h1>Register</h1>
<form method="post">
<p>Username: <input type="text" name="username"></p>
<p>Password: <input type="password" name="password"></p>
<p><input type="submit" value="Register"></p>
</form>
"""
Note: In the HTML page that handles the form,<form>Must be setmethod="post", otherwise the data will be sent via the URL query string (GET method), and sensitive information will be exposed in the URL.
Get JSON data — request.json
In modern web development, JSON is the most common data format.
When the client sendsContent-Type: application/jsona request, userequest.jsonGet the parsed data:
Example
def create_user():
# request.json returns JSON data already parsed into a Python dict
data = request.json # For example, the client sends {"name": "example", "email": "test@example.com"}
# Safely get the field
name = data.get("name", "Unknown")
email = data.get("email", "Not provided")
# Return dict directly, Flask automatically converts it to a JSON response
return {
"message": "User created successfully",
"name": name,
"email": email
}
Can be usedcurlor Postman to test:
$ curl -X POST http://127.0.0.1:5000/api/user \
-H "Content-Type: application/json" \
-d '{"name": "example", "email": "test@example.com"}'
{
"message": "用户创建成功",
"name": "example",
"email": "test@example.com"
}
File upload
Use this to handle uploaded files:request.files, combined with the Werkzeug-providedsecure_filename()Ensure the filename is safe:
Example
from werkzeug.utils import secure_filename # Filter dangerous filename characters
# Configure the upload directory (in a real project, this should be read from config)
UPLOAD_DIR = "uploads"
@app.route("/upload", methods=["GET", "POST"])
def upload_file():
if request.method == "POST":
# Check if a file was uploaded
if "file" not in request.files:
return "No file selected", 400
file = request.files["file"]
# User may have submitted an empty form (no file selected)
if file.filename == "":
return "Filename is empty", 400
# secure_filename filters out dangerous characters like path traversal
# For example, "../../etc/passwd" would be processed as "etc_passwd"
filename = secure_filename(file.filename)
# Ensure the upload directory exists
os.makedirs(UPLOAD_DIR, exist_ok=True)
# Save the file
file.save(os.path.join(UPLOAD_DIR, filename))
return fFile {filename} uploaded successfully
# GET request shows upload form
return """
<h1>Upload File</h1>
<form method="post" enctype="multipart/form-data">
<p><input type="file" name="file"></p>
<p><input type="submit" value="Upload"></p>
</form>
"""
If the form has a file upload field,<form>The label must be setenctype="multipart/form-data", otherwise the file data will not be sent by the browser.
Complete Guide to Response Types
View functions can return multiple types of data, and Flask will automatically convert them into appropriate HTTP responses.
Understanding this conversion rule is the key to mastering Flask.
Return string
The returned string serves as the HTML response body, with a default status code of 200 and Content-Type oftext/html。
Return a dictionary or list (JSON)
Automatically calledjsonify()convert to JSON response, with Content-Type set toapplication/json。
Example
def get_posts():
# Return dict, Flask automatically converts to JSON
return {
"status": "ok",
"data": [
{"id": 1, "title": Flask Tutorial},
{"id": 2, "title": RESTful API Design},
]
}
@app.get("/api/tags")
def get_tags():
# Return list, Flask automatically converts to JSON
return ["Python", "Flask", Web Development, "EXAMPLE"]
Returning a tuple—controlling the status code and response headers
The tuple format is very practical and has three forms:
Example
@app.get("/not-found")
def not_found():
return <h1>Page Not Found</h1>, 404
# Form 2: (body, headers_dict)
@app.get("/custom-header")
def custom_header():
return "OK", {"X-Custom-Header": "example"}
# Form 3: (body, status_code, headers_dict)
@app.post("/api/login")
def api_login():
# Return token and custom status code
return {"token": "abc123", "user": "example"}, 201, {"X-RateLimit": "100"}
Redirect
Usageredirect()The function redirects the user to another URL:
Example
app = Flask(__name__)
@app.route("/")
def index():
# Redirect to login page when visiting home page
return redirect(url_for("login"))
@app.route("/login")
def login():
return <h1>Please Log In First</h1>
@app.route("/old-page")
def old_page():
# Old page permanently moved to new page, use 301 status code
return redirect(url_for("new_page"), code=301)
@app.route("/new-page")
def new_page():
return <h1>This is a new page</h1>
The default redirect status code is303 See Other, suitable for redirecting after form submission (PRG pattern).
For permanent migration scenarios, usecode=301。
Terminate Request — abort
Usageabort()Immediately terminate the current request and return an HTTP error:
Example
@app.route("/post/<int:post_id>")
def view_post(post_id):
# Assume article IDs are only 1-100
if post_id < 1 or post_id > 100:
# Immediately return 404, subsequent code will not execute
abort(404)
return f"<h1>Article #{post_id}</h1>"
@app.route("/admin")
def admin():
# Return 403 for unauthorized access
abort(403, description=You do not have permission to access this page)
make_response — manually control the response
When you need to manually set cookies or customize response headers, usemake_response():
Example
@app.route("/set-cookie")
def set_cookie():
# make_response wraps the view function's return value into a Response object
resp = make_response(<h1>Cookie Set</h1>)
# Set cookie on the Response object
resp.set_cookie("theme", "dark", max_age=60*60*24) # Valid for 24 hours
resp.set_cookie("lang", "zh-CN")
# You can also customize response headers
resp.headers["X-Powered-By"] = "EXAMPLE-Flask"
return resp
Quick reference table of common request attributes
| Property | Type | Description | Example value |
|---|---|---|---|
| request.method | str | HTTP Request Method | "GET", "POST" |
| request.path | str | URL Path (without domain name) | "/search" |
| request.args | MultiDict | URL Query Parameters | ?keyword=flask&page=1 |
| request.form | MultiDict | POST Form Data | username=admin |
| request.json | dict or None | JSON Request Body (parsed) | {"name": "example"} |
| request.files | FileMultiDict | Uploaded file | request.files["avatar"] |
| request.headers | Headers | Request headers | request.headers["User-Agent"] |
| request.cookies | dict | Cookie Sent by the Client | request.cookies.get("theme") |
| request.remote_addr | str | Client IP Address | "127.0.0.1" |