Get the Data Received in a Flask Request

Get the data received in a Flask request

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.

Python Flask - request.data.get

For a post request like this, the request.data attribute is like a dictionary. If you have a dictionary in python you can use get to specify a key you want the value for in the dictionary, for example:

example = {"key": "value"}
example.get("key") # gives you "value"

The difference between using get and simply doing example["key"] is that you won't get and error of the key is missing:

example = {"key": "value"}
example.get("other") # gives you None
example["other"] # raises KeyError

You can also (as in your example) give a default value for a missing key:

example = {"key": "value"}
example.get("key") # gives you "value"
example.get("other", "different value") # gives you "different value"

So, for your end point the code is trying to get a series of data points from the post request using data.get and is using default values (empty string or 1) for missing values.

Getting Flask Request Data

If member is of type bytes, then you should convert it to a string using the decode() function. Then convert that result to JSON so that you can read it in your browser using the jsonify function:

@app.route("/lookupmember", methods=["POST"])
def lookupmember():
member = request.data
print(member)
return jsonify(member.decode("utf-8"))

perform GET Request with output from POST Request in Flask

Yes, there is :)

Have a look at the following code:

class LocalStore:
def __call__(self, f: callable):
f.__globals__[self.__class__.__name__] = self
return f


# ------------upload-file-----------------------------------------#
@flask_class.route('/uploadajax', methods=['POST', 'GET'])
@LocalStore() # creates store for this unique method only
def receave_file():
if request.method == 'POST':
LocalStore.post_headers= request.headers
LocalStore.post_body = request.body
LocalStore.post_json = request.get_json()
LocalStore.post_params = request.params
LocalStore.answer_to_everything = 42

print("POST request stored.")
return jsonify({"response": "Thanks for your POST!"})
else:
try:
print("This is a GET request.")
print("POST headers were:", LocalStore.post_headers)
print("POST params were :", LocalStore.post_params)
print("POST body was :", LocalStore.post_body)
print("The answer is :", LocalStore.answer_to_everything)
return jsonify({"postHeadersWere": LocalStore.post_headers})
except AttributeError:
return jsonify({"response":"You have to make a POST first!"})

I created a special class which "injects" its reference into the __globals__ dictionary of the method. If you type the class name in the method, it will be the object reference, not the class reference. Be aware of that!

You then just need to add @LocalStore underneath the @app.route(...) of your application because the store needs to be routed with the method...

I think it's a quite elegant way that saves you the definition of 5 global variables for 5 different methods

Accessing incoming POST data in Flask

You're inadvertently sending the wrong Content Type.

By default, curl's -d flag will send POST data with content-type application/x-www-form-urlencoded. Since you're not sending data in the format that it's expecting (key=value), it's dropping the data altogether. For JSON data, you'll need to send the HTTP request with the content-type set to application/json like so:

curl -XPOST -H "Content-Type: application/json" 'http://127.0.0.1:5000/?thing1=1' -d '{"thing2":2}'

Also, flask's request.form field only contains POST form data, not other content types. You can access the raw POST request body with request.data or, more convenienty, the parsed JSON data using request.get_json.

Below is a fixed version of your example:

from flask import Flask, request
import json
app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def refresh():
params = {
'thing1': request.values.get('thing1'),
'thing2': request.get_json().get('thing2')
}
return json.dumps(params)


app.run()

UPDATE: I misspoke earlier - request.body should actually be request.data. Also as it turns out request.json is deprecated and request.get_json should be used now instead. The original post has been updated.

Get raw POST body in Python Flask regardless of Content-Type header

Use request.get_data() to get the raw data, regardless of content type. The data is cached and you can subsequently access request.data, request.json, request.form at will.

If you access request.data first, it will call get_data with an argument to parse form data first. If the request has a form content type (multipart/form-data, application/x-www-form-urlencoded, or application/x-url-encoded) then the raw data will be consumed. request.data and request.json will appear empty in this case.

get request data from Flask redirect

First of all, an API should always return a response in a format that is consistent and predictable. The code for member_get returns JSON in case of success but plain text in case of failure. This is not okay. You should return JSON always, with the appropriate HTTP status code. Here you are using 404 to express Not found, this is good.
You can use the jsonify function in Flask for that. And maybe normalize the response, so that is always has the same shape, whether the member ID is found or not.

Otherwise, parsing the response from your API will be harder because it is not consistent depending on the scenario.

Second point, if I understand it right: if you want to invoke the route '/member/' from within your API, you could simply do:

return member_get(id)

You call the function that is attached to the route, not the route itself. Of course you could actually fetch the page with the requests module but this is unnecessary, since the function is available internally.



Related Topics



Leave a reply



Submit