【问题标题】:Flask-WTF 'FileField' object has no attribute 'has_file'Flask-WTF 'FileField' 对象没有属性 'has_file'
【发布时间】:2020-01-02 06:23:24
【问题描述】:

我结合 Flask-WTFFlask-upload 来处理我的应用程序上的文件上传。

我的包版本是:

Flask-Uploads==0.2.1
Flask-WTF==0.11
WTForms==2.1

这是我的代码的 sn-p:

forms.py

from flask_wtf import Form
from flask_wtf.file import FileAllowed, FileRequired
from wtforms.fields import (StringField, SubmitField, FileField)
from wtforms.validators import InputRequired, Length
from app import photos

class AddCourseForm(Form):
    name = StringField('Course name', validators=[InputRequired(), Length(1, 100)])
    image = FileField('image', validators=[FileRequired(), FileAllowed(photos, 'Images only!')])
    submit = SubmitField('Add course')

这里是上传代码的sn-p:

@operator.route('/add-course', methods=['GET', 'POST'])
def add_course():
    form = AddCourseForm()
    if form.validate_on_submit():
        course_name = form.name.data
        filename = photos.save(request.files['image'], name="courses/" + course_name + "_course.")
        course = Course(name=course_name, image=filename)
        db.session.add(course)
        db.session.commit()
        flash('Successfully added {} '.format(course.course_name()) + 'course', 'success')
        return redirect(url_for('operator.courses'))
    return render_template('main/operator/add_course.html', form=form)

但是,当我提交时,我收到以下错误:

AttributeError: 'FileField' object has no attribute 'has_file'

然后我尝试通过直接传递扩展来关注这个documentation,而不使用 Flask-Upload:

image = FileField('image', validators=[FileRequired(), FileAllowed(['jpg', 'png'], 'Images only!')])

但我仍然遇到同样的错误。

那么,我的代码有什么问题..? 请,任何帮助将不胜感激:)

【问题讨论】:

    标签: python flask flask-wtforms wtforms flask-uploads


    【解决方案1】:

    您从 wtforms 库导入 FileField

    from wtforms.fields import (StringField, SubmitField, FileField)
    

    ...但FileField.has_file() 方法是特定于Flask-WTF 的。

    您需要将FileField 添加到来自flask_wtf.file 的其他导入中。

    您可以访问Flask-WTF.file.FileFieldhere的API文档。

    当前的实现(found here)是:

    class FileField(_FileField):
        """Werkzeug-aware subclass of :class:`wtforms.fields.FileField`."""
    
        def process_formdata(self, valuelist):
            valuelist = (x for x in valuelist if isinstance(x, FileStorage) and x)
            data = next(valuelist, None)
    
            if data is not None:
                self.data = data
            else:
                self.raw_data = ()
    
        def has_file(self):
            """Return ``True`` if ``self.data`` is a
            :class:`~werkzeug.datastructures.FileStorage` object.
            .. deprecated:: 0.14.1
                ``data`` is no longer set if the input is not a non-empty
                ``FileStorage``. Check ``form.data is not None`` instead.
            """
    
            warnings.warn(FlaskWTFDeprecationWarning(
                '"has_file" is deprecated and will be removed in 1.0. The data is '
                'checked during processing instead.'
            ))
            return bool(self.data)
    

    如您所见,该类继承自标准 wtforms 实现(在模块中命名为 _FileField),但对其进行了扩展以覆盖 process_formdata() 方法并添加了 has_file() 方法。

    还请注意,他们正在贬低该方法,并建议您只检查该字段的 data 属性 - 它不完全是技术实现,因此您可以做他们所做的事情来获得相同的功能:bool(field.data) .

    作为参考,这里是 wtforms FileField 的实现:

    class FileField(Field):
        """Renders a file upload field.
        By default, the value will be the filename sent in the form data.
        WTForms **does not** deal with frameworks' file handling capabilities.
        A WTForms extension for a framework may replace the filename value
        with an object representing the uploaded data.
        """
    
        widget = widgets.FileInput()
    
        def _value(self):
            # browser ignores value of file input for security
            return False
    

    ...这表明它没有任何超出基础Field 类定义的方法。

    【讨论】:

      猜你喜欢
      • 2016-08-24
      • 2015-06-12
      • 2013-10-12
      • 1970-01-01
      • 1970-01-01
      • 2016-03-13
      • 2018-03-15
      • 2015-04-14
      • 1970-01-01
      相关资源
      最近更新 更多