gpt4 book ai didi

python - 在 Flask 中使用隐藏字段_method 更改请求方法

转载 作者:太空狗 更新时间:2023-10-29 20:26:08 24 4
gpt4 key购买 nike

开始学习 Python 和 Flask 作为学习练习,并且来自 PHP/Symfony2,我可以向表单添加隐藏的 _method 字段以使用 DELETE 或 PUT 覆盖 POST 方法。

似乎 Flask 本身不支持这个,我一直在思考各种想法,包括 http://flask.pocoo.org/snippets/38/ ,这有效,但涉及将覆盖放在表单操作中,而不是作为隐藏字段,IMO 使 URL 看起来难看。

上述地址的注释中有一个片段,它使 _method 从路由的角度工作,但也如那里所讨论的那样,如果您随后尝试访问 View 中的 request.form,确实会导致请求挂起。

有人对此有解决方法吗?如果没有,我会像 POST 一样处理所有事情,但如果能够找到一种方法让它工作,那就太好了。

干杯。


编辑:这是供任何想看的人看的代码:

模板:

<form action="{{ url_for('login') }}" method="POST">
<input type="hidden" name="_method" value="PUT">
<input class="span12" name="email" type="text" placeholder="E-mail address" value="{{ email }}">
<input class="span12" name="password" type="password" placeholder="Your password">
<a href="{{ url_for('reset_password') }}" class="forgot">Forgot password?</a>
<div class="remember">
<input id="remember-me" type="checkbox">
<label for="remember-me">Remember me</label>
</div>
<input class="btn-glow primary login" type="submit" name="submit" value="Log in">
</form>

应用程序/__init__.py

from flask import Flask
from werkzeug.wrappers import Request

class MethodRewriteMiddleware(object):
def __init__(self, app, input_name='_method'):
self.app = app
self.input_name = input_name

def __call__(self, environ, start_response):
request = Request(environ)

if self.input_name in request.form:
method = request.form[self.input_name].upper()

if method in ['GET', 'POST', 'PUT', 'DELETE']:
environ['REQUEST_METHOD'] = method

return self.app(environ, start_response)

app = Flask(__name__)
app.wsgi_app = MethodRewriteMiddleware(app.wsgi_app)
from app import views

查看:

from flask import render_template
@app.route('/user/login', methods=['GET','POST','PUT'])
def login():
emailvalue = 'test@test.com'
if request.method == 'PUT':
emailvalue = request.form['email']
return render_template('login.html', email=emailvalue)

最佳答案

正如您已经指出的那样,您的中间件使后面的 request.form 为空。这是因为 request.form 正在从类似文件的对象中读取。引用 PEP 333 :

wsgi.input -- An input stream (file-like object) from which the HTTP request body can be read. (The server or gateway may perform reads on-demand as requested by the application, or it may pre- read the client's request body and buffer it in-memory or on disk, or use any other technique for providing such an input stream, according to its preference.)

请注意,本段没有告诉我们这个“类文件对象”是否会提供任何将指针重置为文件开头的可能性。事实上,如果我们尝试以下应用程序:

from werkzeug.serving import run_simple

def app(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
yield str(dir(environ['wsgi.input']))

run_simple('localhost', 5000, app)

它没有显示此文件对象具有 seek 方法的任何索引。

因此,您可以做的是将所有内容读入名为data 的字节串,并将wsgi.input 替换为BytesIO( data),它确实有一个可以使用的 seek 方法。 这样做会带来几个缺点,最明显的是所有上传的数据在传递给应用程序之前都被保证完全读入内存。可能还有一些我自己不知道的危险边缘情况,这就是为什么我绝不会冒险在实际应用程序中尝试以下操作:

from werkzeug.formparser import parse_form_data
from werkzeug.wsgi import get_input_stream
from io import BytesIO

class MethodMiddleware(object):
"""Don't actually do this. The disadvantages are not worth it."""
def __init__(self, app):
self.app = app

def __call__(self, environ, start_response):
if environ['REQUEST_METHOD'].upper() == 'POST':
environ['wsgi.input'] = stream = \
BytesIO(get_input_stream(environ).read())
formdata = parse_form_data(environ)[1]
stream.seek(0)

method = formdata.get('_method', '').upper()
if method in ('GET', 'POST', 'PUT', 'DELETE'):
environ['REQUEST_METHOD'] = method

return self.app(environ, start_response)

关于python - 在 Flask 中使用隐藏字段_method 更改请求方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17233931/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com