ddinchev
ddinchev

Reputation: 34673

Get the data received in a Flask request

I want to be able to get the data sent to my Flask app. I've tried accessing request.data but it is an empty string. How do you access request data?

from flask import request

@app.route('/', methods=['GET', 'POST'])
def parse_request():
    data = request.data  # data is empty
    # need posted data here

The answer to this question led me to ask Get raw POST body in Python Flask regardless of Content-Type header next, which is about getting the raw data rather than the parsed data.

Upvotes: 1293

Views: 1926283

Answers (26)

Little Roys
Little Roys

Reputation: 5781

Here's an example of parsing posted JSON data and echoing it back.

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/foo', methods=['POST']) 
def foo():
    data = request.json
    return jsonify(data)

To post JSON with curl:

curl -i -H "Content-Type: application/json" -X POST -d '{"userId":"1", "username": "fizz bizz"}' http://localhost:5000/foo

Or to use Postman:

using postman to post JSON

Upvotes: 178

I went through all the answers above, however, I noticed no one really talked about when you receive data from Client-side (when your client side is of different origin e.g. react app) to Server-side then you also need to handle OPTIONS pre-flight request in Flask to allow Cross-Origin access otherwise CORS error is thrown. After you handle that, then usual process is to use get_json() method on request object. Following is the code that works for me:

@app.route("/read_row_to_customer_sheet", methods=["POST", "OPTIONS"])
def read_row_to_customer_sheet():
    if request.method == "OPTIONS":
        response = make_response()
        response.headers.add("Access-Control-Allow-Origin", "*")
        response.headers.add('Access-Control-Allow-Headers', "*")
        response.headers.add("Content-Type", "application/json")
        return response
    elif request.method == 'POST':
        form = request.get_json()
        print(form)
        # your custom logic goes here
        response = make_response()
        response.headers.add("Access-Control-Allow-Origin", "*")
        return response 

Also make sure you put request.get_json() in elif block not at the beginning of function. Otherwise you will encounter the CORS error at client-side and possibly 415 error at server side because when you receive the pre-flight OPTIONS request the function will try to decode it as json because you placed the request.get_json() at the beginning, therefore, following control-flow is wrong:

### WRONG Route Function
@app.route("/read_row_to_customer_sheet", methods=["POST", "OPTIONS"])
def read_row_to_customer_sheet():
    form = request.get_json()
    if request.method == "OPTIONS":
        response = make_response()
        response.headers.add("Access-Control-Allow-Origin", "*")
        response.headers.add('Access-Control-Allow-Headers', "*")
        response.headers.add("Content-Type", "application/json")
        return response
    elif request.method == 'POST':
        print(form)
        # your custom logic goes here
        response = make_response()
        response.headers.add("Access-Control-Allow-Origin", "*")
        return response 

Upvotes: 0

Ssali Jonathan
Ssali Jonathan

Reputation: 97

To get form data, try this, The request object allows us to get access to the data that come from a request. it can also help us access other information about a request. Hope that helps. :)

from flask import Flask, request


app = Flask(__name__)

@app.get('/')
def index():
  json_data = request.get_json() #this will get the json data and return a dictionary containing the data sent
  
  form_data = request.form #this will get the form data return a dictionary of the data submitted in a form


  #such can be accessed in the following way
   username = json_data.get('username')
   email = form_data.get('email') # this will be value from the email input
  ....

Upvotes: 2

Nikunj
Nikunj

Reputation: 77

Try this

 json_data = request.form or request.get_json()
 data = dict(json_data)

It'll get both the form and JSON data together and convert it into the dictionary

Upvotes: 1

bkoiki950
bkoiki950

Reputation: 355

You can get request data from

  1. request.form for form data, this includes form and file data,
  2. request.json and request.get_json for JSON data
  3. request.headers for headers
  4. request.args to get query params

They're all like a dictionary, use request.form['name'] if you know the key exists, or request.form.get('name') if it is optional.

Upvotes: 31

Rapace-bleu
Rapace-bleu

Reputation: 49

I just faced the same need. I have to save information in case of any unexpected situation. So, I use the following formula:

Info = "%s/%s/%s" % (request.remote_addr, repr(request), repr(session))

repr(request) will give a string representation of the basic information. You could add user-agent data with: request.headers.get('User-Agent')

I also save the session continent as it could contain valuable information

Upvotes: -2

Nimit Gupta
Nimit Gupta

Reputation: 141

Try - >

from flask import request

@app.route('/', methods=['GET', 'POST'])
def parse_request():
    if request.method == 'POST':
       data = request.form.get('data')

Upvotes: -4

Robert
Robert

Reputation: 32745

The docs describe the attributes available on the request object (from flask import request) during a request. In most common cases request.data will be empty because it's used as a fallback:

request.data Contains the incoming request data as string in case it came with a mimetype Flask does not handle.

  • request.args: the key/value pairs in the URL query string
  • request.form: the key/value pairs in the body, from a HTML post form, or JavaScript request that isn't JSON encoded
  • request.files: the files in the body, which Flask keeps separate from form. HTML forms must use enctype=multipart/form-data or files will not be uploaded.
  • request.values: combined args and form, preferring args if keys overlap
  • request.json: parsed JSON data. The request must have the application/json content type, or use request.get_json(force=True) to ignore the content type.

All of these are MultiDict instances (except for json). You can access values using:

  • request.form['name']: use indexing if you know the key exists
  • request.form.get('name'): use get if the key might not exist
  • request.form.getlist('name'): use getlist if the key is sent multiple times and you want a list of values. get only returns the first value.

Upvotes: 2229

Murad
Murad

Reputation: 1162

Import request:

from flask import request

URL query parameters:

name = request.args.get("name")
age = request.args.get("age")

Form Input:

name = request.form.get('name')
age = request.form.get('age')

OR (use indexing if you know the key exists, specify the name of input fields)

name = request.form['name']
age = request.form['age']

JSON Data (for content type application/json)

data = request.get_json()

Upvotes: 26

Phoebe
Phoebe

Reputation: 138

When writing a Slack bot, which is supposed to send JSON data, I got a payload where the Content-Type was application/x-www-form-urlencoded.

I tried request.get_json() and it didn't work.

@app.route('/process_data', methods=['POST'])
def process_data():
   req_data = request.get_json(force=True)

Instead I used request.form to get the form data field that contained JSON, then loaded that.

from flask import json

@ app.route('/slack/request_handler', methods=['POST'])
def request_handler():
   req_data = json.loads(request.form["payload"])

Upvotes: 12

James
James

Reputation: 63

request.data

This is great to use but remember that it comes in as a string and will need iterated through.

Upvotes: -3

Divyani Singh
Divyani Singh

Reputation: 531

@app.route('/addData', methods=['POST'])
def add_data():
     data_in = mongo.db.Data
     id = request.values.get("id")
     name = request.values.get("name")
     newuser = {'id' : id, 'name' : name}
     if voter.find({'id' : id, 'name' : name}).count() > 0:
            return "Data Exists"
     else:
            data_in.insert(newuser)
            return "Data Added"

Upvotes: 6

Dulangi_Kanchana
Dulangi_Kanchana

Reputation: 1233

Here's an example of posting form data to add a user to a database. Check request.method == "POST" to check if the form was submitted. Use keys from request.form to get the form data. Render an HTML template with a <form> otherwise. The fields in the form should have name attributes that match the keys in request.form.

from flask import Flask, request, render_template

app = Flask(__name__)

@app.route("/user/add", methods=["GET", "POST"])
def add_user():
    if request.method == "POST":
        user = User(
            username=request.form["username"],
            email=request.form["email"],
        )
        db.session.add(user)
        db.session.commit()
        return redirect(url_for("index"))

    return render_template("add_user.html")
<form method="post">
    <label for="username">Username</label>
    <input type="text" name="username" id="username">
    <label for="email">Email</label>
    <input type="email" name="email" id="email">
    <input type="submit">
</form>

Upvotes: 16

ivanleoncz
ivanleoncz

Reputation: 10005

To get request.form as a normal dictionary , use request.form.to_dict(flat=False).

To return JSON data for an API, pass it to jsonify.

This example returns form data as JSON data.

@app.route('/form_to_json', methods=['POST'])
def form_to_json():
    data = request.form.to_dict(flat=False)
    return jsonify(data)

Here's an example of POST form data with curl, returning as JSON:

$ curl http://127.0.0.1:5000/data -d "name=ivanleoncz&role=Software Developer"
{
  "name": "ivanleoncz", 
  "role": "Software Developer"
}

Upvotes: 39

vaishali KUNJIR
vaishali KUNJIR

Reputation: 1077

To post JSON with jQuery in JavaScript, use JSON.stringify to dump the data, and set the content type to application/json.

var value_data = [1, 2, 3, 4];

$.ajax({
    type: 'POST',
    url: '/process',
    data: JSON.stringify(value_data),
    contentType: 'application/json',
    success: function (response_data) {
        alert("success");
    }   
});

Parse it in Flask with request.get_json().

data = request.get_json()

Upvotes: 18

Ravin Gupta
Ravin Gupta

Reputation: 853

Use request.get_json() to get posted JSON data.

data = request.get_json()
name = data.get('name', '')

Use request.form to get data when submitting a form with the POST method.

name = request.form.get('name', '')

Use request.args to get data passed in the query string of the URL, like when submitting a form with the GET method.

request.args.get("name", "")

request.form etc. are dict-like, use the get method to get a value with a default if it wasn't passed.

Upvotes: 27

Paul Gowder
Paul Gowder

Reputation: 2539

If the body is recognized as form data, it will be in request.form. If it's JSON, it will be in request.get_json(). Otherwise the raw data will be in request.data. If you're not sure how data will be submitted, you can use an or chain to get the first one with data.

def get_request_data():
    return (
        request.args
        or request.form
        or request.get_json(force=True, silent=True)
        or request.data
    )

request.args contains args parsed from the query string, regardless of what was in the body, so you would remove that from get_request_data() if both it and a body should data at the same time.

Upvotes: 12

freezed
freezed

Reputation: 1339

When posting form data with an HTML form, be sure the input tags have name attributes, otherwise they won't be present in request.form.

@app.route('/', methods=['GET', 'POST'])
def index():
    print(request.form)
    return """
<form method="post">
    <input type="text">
    <input type="text" id="txt2">
    <input type="text" name="txt3" id="txt3">  
    <input type="submit">
</form>
"""
ImmutableMultiDict([('txt3', 'text 3')])

Only the txt3 input had a name, so it's the only key present in request.form.

Upvotes: 5

Zavec
Zavec

Reputation: 215

If the content type is recognized as form data, request.data will parse that into request.form and return an empty string.

To get the raw data regardless of content type, call request.get_data(). request.data calls get_data(parse_form_data=True), while the default is False if you call it directly.

Upvotes: 11

Daniel
Daniel

Reputation: 411

The raw data is passed in to the Flask application from the WSGI server as request.stream. The length of the stream is in the Content-Length header.

length = request.headers["Content-Length"]
data = request.stream.read(length)

It is usually safer to use request.get_data() instead.

Upvotes: 16

zhangqy
zhangqy

Reputation: 943

To parse JSON, use request.get_json().

@app.route("/something", methods=["POST"])
def do_something():
    result = handle(request.get_json())
    return jsonify(data=result)

Upvotes: 12

Tarik Fojnica
Tarik Fojnica

Reputation: 685

To get JSON posted without the application/json content type, use request.get_json(force=True).

@app.route('/process_data', methods=['POST'])
def process_data():
    req_data = request.get_json(force=True)
    language = req_data['language']
    return 'The language value is: {}'.format(language)

Upvotes: 21

Xiao
Xiao

Reputation: 12695

To get the raw post body regardless of the content type, use request.get_data(). If you use request.data, it calls request.get_data(parse_form_data=True), which will populate the request.form MultiDict and leave data empty.

Upvotes: 91

Amitkumar Karnik
Amitkumar Karnik

Reputation: 931

If you post JSON with content type application/json, use request.get_json() to get it in Flask. If the content type is not correct, None is returned. If the data is not JSON, an error is raised.

@app.route("/something", methods=["POST"])
def do_something():
    data = request.get_json()

Upvotes: 57

Fizer Khan
Fizer Khan

Reputation: 92725

For URL query parameters, use request.args.

search = request.args.get("search")
page = request.args.get("page")

For posted form input, use request.form.

email = request.form.get('email')
password = request.form.get('password')

For JSON posted with content type application/json, use request.get_json().

data = request.get_json()

Upvotes: 313

clyfish
clyfish

Reputation: 10450

To get the raw data, use request.data. This only works if it couldn't be parsed as form data, otherwise it will be empty and request.form will have the parsed data.

from flask import request
request.data

Upvotes: 279

Related Questions