Reading the request

Flask · Essentials · 12 min

Every interactive feature starts with reading what the client sent, safely and in the right place.

Inside a view, from flask import request gives you the current request. It is a global-looking object that always refers to the request being handled (how that works is an expert topic).

Where data lives:

  • request.args: the query string, ?q=flask&page=2
  • request.form: fields from an HTML form POST
  • request.get_json(): the parsed JSON body
  • request.files: uploaded files, as FileStorage objects with .filename and .save()
  • request.headers, request.cookies, request.method, request.path

args and form are MultiDicts: a key may appear more than once (?tag=a&tag=b). request.args.get("tag") returns the first value, getlist("tag") all of them.

Use .get() with a default and a type instead of indexing: request.args.get("page", 1, type=int) returns 1 for a missing or non-numeric value. Indexing a missing key, request.form["email"], raises KeyError, which Flask turns into 400 Bad Request. That is fine for required fields, but .get() gives you control over the message.

For JSON, request.get_json() returns 415 Unsupported Media Type if the Content-Type isn't application/json, and 400 if the body is malformed. get_json(silent=True) returns None instead.

Treat all of these as untrusted input. For anything non-trivial, validate with a library such as Pydantic or WTForms, and never trust file.filename: pass it through werkzeug.utils.secure_filename before saving.

Example

from flask import Flask, request

app = Flask(__name__)

@app.get("/search")
def search():
    q = request.args.get("q", "")
    page = request.args.get("page", 1, type=int)
    tags = request.args.getlist("tag")
    return {"q": q, "page": page, "tags": tags}

@app.post("/notes")
def add_note():
    data = request.get_json()
    return {"saved": data["text"], "agent": request.headers.get("User-Agent")}

c = app.test_client()
print(c.get("/search?q=flask&page=x&tag=a&tag=b").json)
# {'page': 1, 'q': 'flask', 'tags': ['a', 'b']}
print(c.post("/notes", json={"text": "hi"}).json["saved"])   # hi
print(c.post("/notes", data="hi").status_code)              # 415

Remember

  • request.args = query string, request.form = form body, get_json() = JSON body
  • Use .get(key, default, type=int) and .getlist() on MultiDicts
  • A missing key via [] becomes a 400 Bad Request

Watch out for

  • Looking for POSTed form fields in request.args, or JSON in request.form.

Check yourself

  1. A form is submitted with method="post". Where are its fields?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: flask.palletsprojects.com/en/stable/quickstart/#accessing-request-data