Я использую:
Рассмотрим этот изолированный пример поведения, о котором я размышляю:
from flask import Flask, url_for, render_template_string
app = Flask(__name__)
@app.route('/hi/', methods=['POST'])
@app.route('/hi/<var>')
def hi(var):
return ''
@app.route('/')
def index():
return render_template_string('''
<html>
<head>
<title>GET or POST</title>
</head>
<body>
<form action = "{{ url_for('path') }}">
<input type='SUBMIT' value='GET'>
</form>
<form action = "{{ url_for('path') }}" method='POST'>
<input type='SUBMIT' value='POST'>
</form>
</body>
</html>''')
@app.route('/path/', methods=['GET', 'POST'])
def path():
return str(url_for('hi', var='Hello', var2='xyz'))
Чтобы прояснить свои намерения, я кратко опишу, что происходит и что я пытаюсь понять:
/hi/
имеет 'необязательный' параметр (<var>
), который принимается только через запрос GET. «Обычная» (то есть без аргументов) конечная точка /hi/
доступна только через метод POST./path/
можно получить доступ как через HTTP-методы GET, так и POST. И он просто возвращает путь для hi
, сгенерированного через url_for('hi', var='Hello', var2='xyz')
./path/
вернет ту же строку, независимо от того, какой метод использовался для доступа к ней (GET или POST). Но это не так: для GET он возвращает /hi/Hello?var2=xyz
(как я, собственно, и ожидал), но для POST я получаю /hi/?var=Hello&var2=xyz
(что кажется мне странным поведением).Путем испытаний и ошибок я смог выяснить, что добавление POST к методам, разрешенным для /hi/<var>
, решает проблему (/hi/Hello?var2=xyz
возвращается /path/
как для GET, так и для POST), то есть:
@app.route('/hi/', methods=['POST'])
@app.route('/hi/<var>', methods=['GET', 'POST'])
def hi(var):
...
Надеюсь, кто-нибудь сможет объяснить мне следующее:
/path/
возвращает разные значения для POST и GET)?/hi/<var>
?🤔 А знаете ли вы, что...
Python подходит для начинающих программистов благодаря своей простоте и читаемости кода.
На ответы наткнулся благодаря Другой вопрос =)
Отвечая на мои собственные вопросы:
(не уверен на 100%, был бы признателен, если бы кто-нибудь подтвердил, что я здесь прав) url_for
имеет необязательный параметр _method
, который по умолчанию соответствует методу, который использовался для возврата представления Текущий. Итак, /path/
действительно возвращает return str(url_for('hi', var='Hello', var2='xyz', _method='GET')
, когда к нему обращались через GET-запрос, и return str(url_for('hi', var='Hello', var2='xyz', _method='POST')
, если к нему обращались через POST-запрос. Вот почему разрешение POST на обеих конечных точках (/hi/<var>
и /hi/
) решает проблему - если POST разрешен только для /hi/
, то return str(url_for('hi', var='Hello', var2='xyz', _method='POST')
проверяет, известен ли var
только /hi/
(а он, очевидно, не известен). С другой стороны, если POST разрешен на обеих конечных точках, то /hi/
и /hi/<var>
проверяются на наличие var
, и /hi/<var>
выбран правильно.
Учитывая предыдущий пункт, исправление теперь довольно очевидно: return str(url_for('hi', var='Hello', var2='xyz', _method='GET')
следует заменить на return str(url_for('hi', var='Hello', var2='xyz')
в исходном фрагменте.