Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flask WTF在失败时通过验证_Flask_Flask Wtforms_Wtforms - Fatal编程技术网

Flask WTF在失败时通过验证

Flask WTF在失败时通过验证,flask,flask-wtforms,wtforms,Flask,Flask Wtforms,Wtforms,我有一个Flask应用程序,在失败时通过用户输入验证。我在应用程序的另一部分中也有类似的代码,可以正常工作。似乎没有调用FileAllowed()方法。如果是的话,那就是真的 这段代码将用户文件上传到s3 MultipleFileField()方法仅对图像文件扩展名进行验证检查。但是,任何文件都通过此检查。InputRequired()方法工作得很好 我尝试了多种不同的方法,但都没有效果。这不是一个CRSF问题,因为其他具有类似代码的路由在没有它的情况下工作 烧瓶/水处理设施表格: cl

我有一个Flask应用程序,在失败时通过用户输入验证。我在应用程序的另一部分中也有类似的代码,可以正常工作。似乎没有调用FileAllowed()方法。如果是的话,那就是真的

这段代码将用户文件上传到s3

MultipleFileField()方法仅对图像文件扩展名进行验证检查。但是,任何文件都通过此检查。InputRequired()方法工作得很好

我尝试了多种不同的方法,但都没有效果。这不是一个CRSF问题,因为其他具有类似代码的路由在没有它的情况下工作

烧瓶/水处理设施表格:

    class AddImgForm(FlaskForm): # should use InputRequired() not DataRequired()
        images= MultipleFileField('Upload Images', validators=[InputRequired(),FileAllowed(['jpg', 'png', 'jpeg', 'tif'])])

        submitBTN2 = SubmitField('Upload')
路线:

@users.route("/account", methods=['GET', 'POST'])
@login_required
def account():
    form = UpdateAccountForm()
    if form.validate_on_submit():

        if form.picture.data: # if a picture is provided save picture

            picture_file= save_picture(form.picture.data, 'p') # saves picture and returns dict with ['filepath'] and ['filename']

            BUCKET= os.environ['BUCKET'] # should send to 'bucket-publicaccess/uploads' bucket in production

            s3= boto3.resource("s3", 
                        region_name = "us-east-2", # had to add "us-east-2" as incorrect region was generated
                        config= boto3.session.Config(signature_version='s3v4'), # must add this to address newer security
                        aws_access_key_id = os.environ["AWS_ACCESS_KEY_ID"],
                        aws_secret_access_key = os.environ["AWS_SECRET_ACCESS_KEY"]) # AWS Generated key pairs

            s3.Bucket(BUCKET).upload_file(picture_file['filepath'], 'uploads/'+ picture_file['filename']) #upload to s3

            current_user.image_file= 'uploads/'+picture_file['filename']
            print(current_user.image_file)
            os.remove(picture_file['filepath']) # remove file from tmp directory

        current_user.username = form.username.data 
        current_user.email = form.email.data
        db.session.commit() # commit changes

        flash('Your account has been updated!', 'success')
        return redirect(url_for('users.account'))
    elif request.method == 'GET':
        form.username.data = current_user.username
        form.email.data = current_user.email
    image_file = current_user.image_file

    return render_template('account.html', title='Account',
                           image_file=image_file, form=form)
HTML:

      <form method="POST" action="" enctype="multipart/form-data" id="addImgForm">
        {{ addImgForm.hidden_tag() }}
        <fieldset class="form-group">
          <div class="form-group">
            {{ addImgForm.images.label() }}
            {{ addImgForm.images(class="form-control-file") }}
            {% if addImgForm.images.errors %}
              {% for error in addImgForm.images.errors %}
                <span class="text-danger">{{ error }}</span></br>
              {% endfor %}
            {% endif %}
          </div>
          <div class="form-group">
            <div class="modal-footer">
              <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
              {{ addImgForm.submitBTN2(class="btn btn-outline-info") }}
            </div>
        </fieldset>
      </form>

{{addImgForm.hidden_tag()}}
{{addImgForm.images.label()}}
{{addImgForm.images(class=“form control file”)}
{%if addImgForm.images.errors%}
{addImgForm.images.errors%中的错误为%0}
{{error}}
{%endfor%} {%endif%} 接近 {{addImgForm.submitbttn2(class=“btn btn outline info”)}

如果您有任何帮助,我们将不胜感激,因为大多数问题都与此失败有关,而此代码总是通过

问题在于
FileAllowed
验证器,它在验证时需要一个
FileStorage
实例,而
MultipleFileField
FileStorage
实例列表传递给验证器。您可以通过编写自己的验证器来克服这一问题,例如:

class MultiFileAllowed(object):

    def __init__(self, upload_set, message=None):
        self.upload_set = upload_set
        self.message = message

    def __call__(self, form, field):

        # FileAllowed only expects a single instance of FileStorage
        # if not (isinstance(field.data, FileStorage) and field.data):
        #     return

        # Check that all the items in field.data are FileStorage items
        if not (all(isinstance(item, FileStorage) for item in field.data) and field.data):
            return

        for data in field.data:
            filename = data.filename.lower()

            if isinstance(self.upload_set, Iterable):
                if any(filename.endswith('.' + x) for x in self.upload_set):
                    return

                raise StopValidation(self.message or field.gettext(
                    'File does not have an approved extension: {extensions}'
                ).format(extensions=', '.join(self.upload_set)))

            if not self.upload_set.file_allowed(field.data, filename):
                raise StopValidation(self.message or field.gettext(
                    'File does not have an approved extension.'
                ))
使用Flask、Flask WTF和Flask Boostrap的简单单文件示例:

from collections import Iterable

from flask_bootstrap import Bootstrap
from flask import Flask, redirect, url_for, render_template_string
from flask_wtf import FlaskForm
from flask_wtf.file import FileAllowed
from markupsafe import Markup
from werkzeug.datastructures import FileStorage
from wtforms.fields import MultipleFileField, SubmitField
from wtforms.validators import InputRequired, StopValidation

app = Flask(__name__)
app.config['SECRET_KEY'] = '123456790'
Bootstrap(app)


class MultiFileAllowed(object):

    def __init__(self, upload_set, message=None):
        self.upload_set = upload_set
        self.message = message

    def __call__(self, form, field):

        if not (all(isinstance(item, FileStorage) for item in field.data) and field.data):
            return

        for data in field.data:
            filename = data.filename.lower()

            if isinstance(self.upload_set, Iterable):
                if any(filename.endswith('.' + x) for x in self.upload_set):
                    return

                raise StopValidation(self.message or field.gettext(
                    'File does not have an approved extension: {extensions}'
                ).format(extensions=', '.join(self.upload_set)))

            if not self.upload_set.file_allowed(field.data, filename):
                raise StopValidation(self.message or field.gettext(
                    'File does not have an approved extension.'
                ))


class ImagesForm(FlaskForm):
    images = MultipleFileField(
        'Upload Images',
        validators=[
            InputRequired(),
            MultiFileAllowed(['jpg', 'png', 'jpeg', 'tif'])
        ]
    )
    submit = SubmitField('Upload')


upload_template = '''
{% import "bootstrap/wtf.html" as wtf %}
<form method="POST" enctype="multipart/form-data">
    {{ wtf.quick_form(form) }}
</form>
'''


@app.route('/')
def index():
    return Markup("<a href='uploads'>Go to the uploads<a>")


@app.route('/uploads', methods=['GET', 'POST'])
def upload():
    form = ImagesForm()
    if form.validate_on_submit():
        if form.images:
            for image in form.images.data:
                print 'Uploaded File: {}'.format(image.filename)

        return redirect(url_for('index'))
    else:
        print form.errors

    return render_template_string(upload_template, form=form)


if __name__ == '__main__':
    app.run()
从集合导入Iterable
从flask_引导导入引导
从烧瓶导入烧瓶,重定向,url,呈现模板字符串
来自flask_wtf进口FlaskForm
允许从flask_wtf.file导入文件
从markupsafe导入标记
从werkzeug.datastructures导入文件存储
从wtforms.fields导入MultipleFileField、SubmitField
从wtforms.validators导入需要的输入,停止验证
app=烧瓶(名称)
app.config['SECRET_KEY']='123456790'
引导(应用程序)
允许类多文件(对象):
def uuu init uuuu(自我,上传集,消息=无):
self.upload\u set=上传\u set
self.message=消息
定义调用(自身、表单、字段):
如果不是(field.data和field.data中的项的全部(isinstance(项,文件存储)):
返回
对于field.data中的数据:
filename=data.filename.lower()
如果isinstance(self.upload\u set,Iterable):
如果有(self.upload\u集合中x的filename.endswith('.'+x)):
返回
提升停止验证(self.message或field.gettext)(
'文件没有批准的扩展名:{extensions}'
).format(扩展名=','.join(self.upload_set)))
如果不是self.upload\u set.file\u允许(field.data,filename):
提升停止验证(self.message或field.gettext)(
“文件没有批准的扩展名。”
))
类别图像窗体(烧瓶窗体):
图像=多字段(
“上传图像”,
验证器=[
InputRequired(),
允许多文件(['jpg','png','jpeg','tif'])
]
)
submit=SubmitField(‘上传’)
上传模板=“”
{%import“bootstrap/wtf.html”作为wtf%}
{{wtf.quick_form(form)}
'''
@应用程序路径(“/”)
def index():
返回标记(“转到上载”)
@app.route('/uploads',methods=['GET','POST'])
def upload():
form=ImagesForm()
if form.validate_on_submit():
如果是form.images:
对于form.images.data中的图像:
打印“上载的文件:{}”。格式(image.filename)
返回重定向(url_for('index'))
其他:
打印表单错误
返回渲染模板字符串(上传模板,表单=表单)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
app.run()

问题在于
FileAllowed
验证器,它在验证时需要一个
FileStorage
实例,而
multiplefield
FileStorage
实例列表传递给验证器。您可以通过编写自己的验证器来克服这一问题,例如:

class MultiFileAllowed(object):

    def __init__(self, upload_set, message=None):
        self.upload_set = upload_set
        self.message = message

    def __call__(self, form, field):

        # FileAllowed only expects a single instance of FileStorage
        # if not (isinstance(field.data, FileStorage) and field.data):
        #     return

        # Check that all the items in field.data are FileStorage items
        if not (all(isinstance(item, FileStorage) for item in field.data) and field.data):
            return

        for data in field.data:
            filename = data.filename.lower()

            if isinstance(self.upload_set, Iterable):
                if any(filename.endswith('.' + x) for x in self.upload_set):
                    return

                raise StopValidation(self.message or field.gettext(
                    'File does not have an approved extension: {extensions}'
                ).format(extensions=', '.join(self.upload_set)))

            if not self.upload_set.file_allowed(field.data, filename):
                raise StopValidation(self.message or field.gettext(
                    'File does not have an approved extension.'
                ))
使用Flask、Flask WTF和Flask Boostrap的简单单文件示例:

from collections import Iterable

from flask_bootstrap import Bootstrap
from flask import Flask, redirect, url_for, render_template_string
from flask_wtf import FlaskForm
from flask_wtf.file import FileAllowed
from markupsafe import Markup
from werkzeug.datastructures import FileStorage
from wtforms.fields import MultipleFileField, SubmitField
from wtforms.validators import InputRequired, StopValidation

app = Flask(__name__)
app.config['SECRET_KEY'] = '123456790'
Bootstrap(app)


class MultiFileAllowed(object):

    def __init__(self, upload_set, message=None):
        self.upload_set = upload_set
        self.message = message

    def __call__(self, form, field):

        if not (all(isinstance(item, FileStorage) for item in field.data) and field.data):
            return

        for data in field.data:
            filename = data.filename.lower()

            if isinstance(self.upload_set, Iterable):
                if any(filename.endswith('.' + x) for x in self.upload_set):
                    return

                raise StopValidation(self.message or field.gettext(
                    'File does not have an approved extension: {extensions}'
                ).format(extensions=', '.join(self.upload_set)))

            if not self.upload_set.file_allowed(field.data, filename):
                raise StopValidation(self.message or field.gettext(
                    'File does not have an approved extension.'
                ))


class ImagesForm(FlaskForm):
    images = MultipleFileField(
        'Upload Images',
        validators=[
            InputRequired(),
            MultiFileAllowed(['jpg', 'png', 'jpeg', 'tif'])
        ]
    )
    submit = SubmitField('Upload')


upload_template = '''
{% import "bootstrap/wtf.html" as wtf %}
<form method="POST" enctype="multipart/form-data">
    {{ wtf.quick_form(form) }}
</form>
'''


@app.route('/')
def index():
    return Markup("<a href='uploads'>Go to the uploads<a>")


@app.route('/uploads', methods=['GET', 'POST'])
def upload():
    form = ImagesForm()
    if form.validate_on_submit():
        if form.images:
            for image in form.images.data:
                print 'Uploaded File: {}'.format(image.filename)

        return redirect(url_for('index'))
    else:
        print form.errors

    return render_template_string(upload_template, form=form)


if __name__ == '__main__':
    app.run()
从集合导入Iterable
从flask_引导导入引导
从烧瓶导入烧瓶,重定向,url,呈现模板字符串
来自flask_wtf进口FlaskForm
允许从flask_wtf.file导入文件
从markupsafe导入标记
从werkzeug.datastructures导入文件存储
从wtforms.fields导入MultipleFileField、SubmitField
从wtforms.validators导入需要的输入,停止验证
app=烧瓶(名称)
app.config['SECRET_KEY']='123456790'
引导(应用程序)
允许类多文件(对象):
def uuu init uuuu(自我,上传集,消息=无):
self.upload\u set=上传\u set
self.message=消息
定义调用(自身、表单、字段):
如果不是(field.data和field.data中的项的全部(isinstance(项,文件存储)):
返回
对于field.data中的数据:
filename=data.filename.lower()
如果isinstance(self.upload\u set,Iterable):
如果有(self.upload\u集合中x的filename.endswith('.'+x)):
返回
提升停止验证(self.message或field.gettext)(
'文件没有批准的扩展名:{extensions}'
).format(扩展名=','.join(self.upload_set)))
如果不是self.upload\u set.file\u允许(field.data,filename):
提升停止验证(self.message或field.gettext)(
“文件没有批准的扩展名。”
))
类别图像窗体(烧瓶窗体):
图像=多字段(
“上传图像”,