Как получить данные, полученные в запросе Flask
Я хочу получать данные, отправленные в мое приложение Flask. Я пытался получить доступ request.data
но это пустая строка. Как вы получаете доступ к данным запроса?
@app.route('/', methods=['GET', 'POST'])
def parse_request():
data = request.data # data is empty
# need posted data here
Ответ на этот вопрос заставил меня спросить Получить необработанное тело POST в Python Flask независимо от следующего заголовка Content-Type, который касается получения необработанных данных, а не проанализированных данных.
26 ответов
Документы описывают атрибуты, доступные по запросу. В большинстве распространенных случаев request.data
будет пустым, потому что он используется как запасной вариант:
request.data
Содержит данные входящего запроса в виде строки на случай, если они поступили с mimetype, который Flask не обрабатывает.
request.args
: пары ключ / значение в строке запроса URLrequest.form
: пары ключ / значение в теле, из HTML-формы публикации или запроса JavaScript, который не закодирован в JSONrequest.files
: файлы в теле, которые Flask хранит отдельноform
, HTML-формы должны использоватьenctype=multipart/form-data
или файлы не будут загружены.request.values
: комбинированныйargs
а такжеform
предпочитаяargs
если ключи перекрываются
Все это MultiDict
экземпляров. Вы можете получить доступ к значениям, используя:
request.form['name']
: используйте индексацию, если вы знаете, что ключ существуетrequest.form.get('name')
: использоватьget
если ключ может не существоватьrequest.form.getlist('name')
: использоватьgetlist
если ключ отправляется несколько раз, и вы хотите список значений.get
возвращает только первое значение.
Это просто так
Для параметра URL Query используйте request.args
search = request.args.get("search")
page = request.args.get("page")
Для ввода формы используйте request.form
email = request.form.get('email')
password = request.form.get('password')
Для типа данных application/json используйте request.data
# data in string format and you have to parse into dictionary
data = request.data
dataDict = json.loads(data)
Я привожу полный пример приложения / JSON:
from flask import Flask, abort, request
import json
app = Flask(__name__)
@app.route('/foo', methods=['POST'])
def foo():
if not request.json:
abort(400)
print request.json
return json.dumps(request.json)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
используйте Почтальон для почтового запроса:
используйте команду curl:
curl -i -H "Content-Type: application/json" -X POST -d '{"userId":"1", "username": "fizz bizz"}' http://localhost:5000/foo
PS Для примера параметра URL Query вы можете увидеть мой ответ в разделе Несколько параметров в приложении Flask.
Если вы хотите получить необработанное тело сообщения независимо от типа контента, вы должны использовать request.get_data()
, так как request.form
преобразуется в werkzeug.ImmutableMultiDict
формат.
У Flask есть еще один ярлык для JSON:
Заголовок:
{Content-Type: application/json}
@app.route("/something", methods=["POST"])
def do_something():
data = request.get_json()
С помощью request.form
,
Вместо того, чтобы получать данные одной формы (request.form["field_name"]
), вы можете получить все опубликованные данные, анализируя ImmutableDict
предоставлено request.form
объект, как это:
Колба (Маршрут)
@app.route('/data', methods=['POST'])
def f_data():
if request.method == "POST":
fields = [k for k in request.form]
values = [request.form[k] for k in request.form]
data = dict(zip(fields, values))
return jsonify(data)
Ракушка
$ curl http://127.0.0.1:5000/data -d "name=ivanleoncz&role=Software Developer"
{
"name": "ivanleoncz",
"role": "Software Developer"
}
Для более подробной информации, это Gist.
Вы можете получить данные запроса от
-
request.form
для данных формы это включает данные формы и файла, -
request.json
а такжеrequest.get_json
для данных JSON -
request.headers
для заголовков -
request.args
чтобы получить параметры запроса
Кроме того, они все как словарь, но тогда они не словари, поэтому лучше не делать
request.form['name']
и вместо этого сделать
request.form.get('name')
.
from flask import request
content = request.get_json()
name = content.get('name', '')
получить данные, если запрос типа JSON, и вы также можете упомянуть параметры по умолчанию вместе с ним
from flask import request
content = request.form
name = content.get('name', '')
получить данные, если форма запроса
from flask import request
request.args.get("name", "")
получить параметры из URL с помощью запроса GET
Запрос на импорт:
from flask import request
Параметры URL-запроса:
name = request.args.get("name")
age = request.args.get("age")
Ввод формы:
name = request.form.get('name')
age = request.form.get('age')
ИЛИ (используйте индексацию, если знаете, что ключ существует, укажите имя полей ввода )
name = request.form['name']
age = request.form['age']
Данные JSON (для типа контента application / json)
data = request.get_json()
@app.route('/', methods=['POST'])
def process_data():
req_data = request.get_json(force=True) # force=True will make sure this works even if a client does not specify application/json
language = req_data['language'] # or whatever key you have in your json
return '''The language value is: {}'''.format(language)
В JavaScript:
var value_data = [1,2,3,4];
$.ajax({
type: 'POST',
url: '/',
data:JSON.stringify(value_data),
success: function (response) {
alert("Data added successfully");
},
});
В питоне:
client_data = request.get_data()
Вот пример публикации данных формы для добавления пользователя в базу данных. Проверьтеrequest.method == "POST"
чтобы проверить, была ли отправлена форма. Используйте ключи отrequest.form
чтобы получить данные формы. Визуализировать HTML-шаблон с<form>
иначе. Поля в форме должны иметьname
атрибуты, соответствующие ключам в 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>
len = request.headers["Content-Length"]
data=request.stream.read()
Теперь данные - это тело запроса
Проще говоря, вы можете получить данные одним из следующих способов:
@app.before_request
def before_request():
g.data = request.get_json() or request.values
Сейчас, g.data
это пример werkzeug.ImmutableMultiDict
, Тогда вы можете использовать g.data
который может удовлетворить большинство ваших требований. Например, вы можете использовать это так:
@app.route("/something", methods=["POST"])
def do_something():
result = handle(g.data)
return jsonify(data=result)
Конечно, вы можете использовать blueprint
вместо app
~~
Это своего рода грязный хак, чтобы получить все данные запроса независимо от того, как они были отправлены, но я серьезно просто использую:
def get_request_info():
args = str(request.args)
form = str(request.form)
files = str(request.files)
maybe_json = request.get_json(silent=True, cache=False)
if maybe_json:
thejson = json.dumps(maybe_json)
else:
thejson = "no json"
return # whatever you want
и затем я просто возвращаю либо строку, которая объединяет их, либо, если мне кажется, что я пропускаю строковые вызовы /json dump, и объединяю все разногласия. затем это может быть зарегистрировано, возвращено в функции представления, что угодно, и вы можете фактически увидеть весь запрос, независимо от того, что он включает.
Моя проблема была похожей. Я получил
payload
POST-запрос, когда пользователь щелкнул
button
из моего слэк-бота. В
Content-Type
было
application/x-www-form-urlencoded
. Я использовал Flask, Python3.
Я попробовал это решение, но оно не сработало
@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)
Мое решение 1 было:
from urllib.parse import parse_qs
# Some code
@ app.route('/slack/request_handler', methods=['POST'])
def request_handler():
# request.get_data() returned a bytestring
# parse_qs() returned a dict from a bytestring. This dict has 1 pair
# I tried payload_dict.keys() to see what keys in the dict and it had one key only
payload_dict = parse_qs(request.get_data())
# Get the value of the key from payload_dict
# Value of the key from payload_dict is an array, length = 1
payload_dict_value_arr = payload_dict[b'payload']
# Get data from the index[0] of the array payload_dict_value_arr
data = payload_dict_value_arr[0]
# convert a string (representation of a Dict)) to a Dict
# Note that if you have single quotes as a part of your keys or values this will
# fail due to improper character replacement.
# This solution is only recommended if you have a strong aversion
# to the eval solution.
datajson = json.loads(data)
# get value of key "channel"
channel = datajson["channel"]
print(channel) {'id': 'D01ACC2E8S3', 'name': 'directmessage'}
Мое решение 2, немного короче:
@ app.route('/slack/request_handler', methods=['POST'])
def request_handler():
payload = request.form # return an ImmutableMultiDict with 1 pair
a1 = payload['payload'] # get value of key 'payload'
# Note that if you have single quotes as a part of your keys or values this will
# fail due to improper character replacement.
# convert a string (representation of a Dict)) to a Dict
a2 = json.loads(a1)
# get value of key "channel"
channel = a2["channel"]
print(channel) # {'id': 'D01ACC2E8S3', 'name': 'directmessage'}
Если тип пантомимы распознан, то оба request.data
а также request.get_data()
вернет пустые строки.
Чтобы получить полное содержание независимо, вам нужно позвонить request.get_data(as_text=True)
,
@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"
Для таких как я, кто забыл (немного) о HTML, обязательно <input>
в вашем <form>
имеет name=""
атрибут!
from flask import Flask, request
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def index():
print("Posted data : {}".format(request.form))
return """
<form method="post">
<input type="text">
<input type="text" id="idtxt2">
<input type="text" name="txt3" id="idtxt3">
<input type="submit" Value="Hopla!">
</form>
"""
if __name__ == "__main__":
app.run()
Результат на консоли:
freezed@machine % python3 run.py
* Serving Flask app "flaskstuff.views" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 268-634-781
127.0.0.1 - - [20/Aug/2018 16:52:59] "POST / HTTP/1.1" 200 -
Posted data : ImmutableMultiDict([('txt3', 'text 3')])
Нет имени атрибута = нет данных в ImmutableMultiDict([])
!
Чтобы получить данные формы, попробуйте следующее. Объект запроса позволяет нам получить доступ к данным, полученным из запроса. это также может помочь нам получить доступ к другой информации о запросе. Надеюсь, это поможет. :)
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
....
Попробуй это
json_data = request.form or request.get_json()
data = dict(json_data)
Он соберет форму и данные JSON и преобразует их в словарь.
from flask import Flask, request, jsonify
@app.route('/added', methods=['POST'])
def add():
data = request.get_json(force=True)
l = {'name': data['name']}
lingual.append(l)
return jsonify({'lang': lingual})
Я просто столкнулся с такой же необходимостью. Я должен сохранить информацию на случай любой неожиданной ситуации. Итак, я использую следующую формулу:
Info = "%s/%s/%s" % (request.remote_addr, repr(request), repr(session))
repr(request) даст строковое представление основной информации. Вы можете добавить данные пользовательского агента с помощью:request.headers.get('User-Agent')
Я также сохраняю континент сеанса, так как он может содержать ценную информацию.
Попробуйте ->
from flask import request
@app.route('/', methods=['GET', 'POST'])
def parse_request():
if request.method == 'POST':
data = request.form.get('data')
request.data
Это удобно использовать, но помните, что он поступает в виде строки и требует повторения.