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 stringrequest.form
: the key/value pairs in the body, from a HTML post form, or JavaScript request that isn't JSON encodedrequest.files
: the files in the body, which Flask keeps separate fromform
. HTML forms must useenctype=multipart/form-data
or files will not be uploaded.request.values
: combinedargs
andform
, preferringargs
if keys overlaprequest.json
: parsed JSON data. The request must have theapplication/json
content type, or userequest.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 existsrequest.form.get('name')
: useget
if the key might not existrequest.form.getlist('name')
: usegetlist
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
Decode HTML Entities in Python String
Two Versions of Python on Linux. How to Make 2.7 the Default
Django [Errno 13] Permission Denied: '/Var/Www/Media/Animals/User_Uploads'
How to Upgrade Python Version to 3.7
How to Clone a List So That It Doesn't Change Unexpectedly After Assignment
Why Does My Recursive Function Return None
How to Add to the Pythonpath in Windows, So It Finds My Modules/Packages
Why Can a Function Modify Some Arguments as Perceived by the Caller, But Not Others
How to Find All Occurrences of a Substring
Strip HTML from Strings in Python
Extracting Text from Ms Word Files in Python
Standard_Init_Linux.Go:178: Exec User Process Caused "Exec Format Error"
Can Python Select What Network Adapter When Opening a Socket
Difference Between _Str_ and _Repr_