我刚刚开始使用Flask进行编码,我想在我的应用程序中的小表单上设置CSRF。我正在关注此http://wtforms.readthedocs.org/en/2.0.2/csrf.html以进行基于会话的实施。我在网上浏览了一段时间以找到类似问题的解决方案,但我没有成功,如果这是一个重复的问题,请道歉。
此代码出现问题:
当我在虚拟环境中运行它时,我会使用AttributeError: 'Request' object has no attribute 'POST'
-
目标:在wtform实例上实现csrf
环境:wtf版本2.02,烧瓶0.10,venv with python 2.7
Traceback (most recent call last):
File "/home/maria/Desktop/ciacicode/fci/venv/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/home/maria/Desktop/ciacicode/fci/venv/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/home/maria/Desktop/ciacicode/fci/venv/lib/python2.7/site-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/maria/Desktop/ciacicode/fci/venv/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/home/maria/Desktop/ciacicode/fci/venv/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/maria/Desktop/ciacicode/fci/venv/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/maria/Desktop/ciacicode/fci/venv/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/home/maria/Desktop/ciacicode/fci/venv/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
TypeError: fci_form() takes exactly 1 argument (0 given)
fci_form.py
from flask import session, request
from flask.ext.wtf import Form
from wtforms import TextField, validators, SubmitField
from wtforms.validators import Required, Length
from wtforms.csrf.session import SessionCSRF
from datetime import timedelta
import config # my config file
# create super class
class MyForm(Form):
class Meta:
csrf = True
csrf_class = SessionCSRF
csrf_secret = config.secret_key
csrf_time_limit = timedelta(minutes=20)
@property
def csrf_context(self):
return request.session
# create a class for the form
class postcodeInput(MyForm):
postcode = TextField('postcode',[validators.Required(message=(u"Where is your postcode?")),validators.Length(min=2, max=10)])
submit = SubmitField('Submit')
views.py
from flask import Flask, render_template, request, __version__, url_for, session, abort, flash, redirect
# importing the class called postcode_input
from fci_form import postcodeInput
import config
import fciUtils
#pdb.set_trace()
app = Flask(__name__)
app.debug = True
# Views of the app
@app.route('/')
def index():
return render_template('home.html')
@app.route('/fci', methods=['GET', 'POST'])
def fci_form():
error = None
form = postcodeInput(request.POST, meta={'csrf_context': request.session})
if form.validate_on_submit():
# handle user input
postcode = request.form['postcode']
# calculate fci
result = fciUtils.fciReturn(postcode)
return render_template('fci_form.html',form = form, result = result)
elif request.method == 'GET':
return render_template('fci_form.html', form = form)
else:
error = 'Enter a valid postcode'
return render_template('fci_form.html', form=form, error=error)
if __name__ == '__main__':
app.secret_key = config.secret_key
app.run(threaded=True)
/ templates文件夹
中的模板是 fci_form.html{% extends 'layout.html' %}
{% block form %}
<section>
<header><h1>...</h1><br></header>
<form action="{{ url_for('fci_form')}}" method='POST'>
<p>Enter your London postcode:</p>
<section>
{% if error %}
<p class="error"><strong>Error: </strong>{{error}}</p>
{% endif %}
{{form.csrf_token}}
{{form.postcode}}
{{form.submit(class_="pure-button")}}
</section>
</form>
</section>
{% endblock %}
{% block result %}
<section>
<h4>{{result}}</h4>
</section>
{% endblock %}
我在这里缺少什么?
答案 0 :(得分:2)
从github README进入WTForms项目:
WTForms是一个灵活的表单验证和呈现库,用于 Python Web开发。 与框架无关,并且可以与 您选择的任何Web框架和模板引擎。
..强调我的。与框架无关的意思是,这不仅是Flask的库,还包括诸如此类的示例(来自https://wtforms.readthedocs.io/en/stable/csrf.html#using-csrf):
def view():
form = UserForm(request.POST)
if request.POST and form.validate():
pass # Form is valid and CSRF succeeded
return render('user.html', form=form)
...不一定是任何网络框架中的工作模式,而只是展示该库工作方式的一般说明。
该示例转换为Flask特定示例可能看起来像这样:
@app.route('/submit', methods=("GET", "POST"))
def submit():
form = UserForm(request.form)
if request.method == "POST" and form.validate():
pass # Form is valid and CSRF succeeded
return render_template('submit.html', form=form)
自述文件继续说:
有许多社区库可以与 流行的框架。
一个这样的示例是Flask-WTF,其围绕WTForms的库的“ hello world”如下所示:
@app.route('/submit', methods=('GET', 'POST'))
def submit():
form = MyForm()
if form.validate_on_submit():
return redirect('/success')
return render_template('submit.html', form=form)
请注意,request.form
不必像原始WTForms示例(MyForm
)那样传递给UserForm(request.form)
构造函数,并且在名为validate_on_submit()
的表单,它既测试请求是一个POST
请求,又测试提交的表单内容是否通过了验证。
POST
可以更轻松地处理将Flask-WTF
数据传递到表单和进行验证的过程,还简化了CSRF令牌管理,可以了解here。
答案 1 :(得分:0)
您的问题是您将/fci
路线定义为:
def fci_form(request):
表示您希望传递参数。但是,Flask不通过函数参数传递request
,而是提供a thread-local request
object。只需删除参数,然后从request
导入flask
:
from flask import request
# and then later
def fci_form():