Flask 和 WTForms - 如何确定文件上传字段是否已提交用于处理目的

Flask and WTForms - How to determine if File Upload field is submitted for processing purposes

我创建了一个带有可选 WTForms 文件字段的表单来上传文件。表单有效...但是提交后,我的 view.py 代码总是尝试处理上传的文件,无论它是否已提交。

如何确定文件是否已上传?我希望我的代码仅在上传内容时才处理上传。

现在,我还没有找到正确的验证方法,所以我的代码正在处理上传的文件,即使没有文件上传。

我目前正在 views.py 中尝试进行区分,但它不起作用(见下文):

    attachFile = False

    if attachment:
        attachFile = True

我也尝试了以下方法来实现某些事情(这些在 views.py 中的完整代码中被注释掉了):

            First attempt: if form.attachment.data is not str:
            Second attempt: if not attachment.filename == "":   
            Third attempt: if (isinstance(attachment,str) == False):
            (Fourth (and current) attempt is above)

我也尝试过以下方法,但在未上传文件时出现以下错误:

    if attachment.data:
        attachFile = True

## AttributeError: 'str' object has no attribute 'data'

forms.py:

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, 
SubmitField, TextAreaField, FileField
from wtforms.fields.html5 import EmailField
from wtforms.validators import DataRequired, Email

class MailerForm(FlaskForm):
    fromName = StringField('fromName', validators=[DataRequired()])
    fromEmail = EmailField('fromEmail', validators=[DataRequired(), Email()])
    subject = StringField('Subject', validators=[DataRequired()])
    toAddress = TextAreaField('toAddress', validators=[DataRequired()])
    message = TextAreaField('message', validators=[DataRequired()])
    attachment = FileField('attachment')
    submit = SubmitField('Send Email')

views.py

@app.route('/mailer/', methods=['GET','POST'])
def mailer():

    # compiled regex to quick and dirty email validation
    EMAIL_REGEX = re.compile(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)")


    form = MailerForm()

    if form.validate_on_submit():
        fromName = form.fromName.data
        fromEmail = form.fromEmail.data  
        subject = form.subject.data
        toAddress = form.toAddress.data
        messageBody = form.message.data
        attachment = form.attachment.data
        newFileName = ""

        attachFile = False

        if attachment:
            attachFile = True


        basedir = os.path.abspath(os.path.dirname(__file__))

        ## lists to track successful and unsuccessful email addresses submitted
        success = []
        failure = []

        ##
        ## split email address
        ##
        addresses = toAddress.split("\n")
        ##
        ## iterate through email addresses, validate, and send
        ##
        for address in addresses:

            address = address.strip()

            if EMAIL_REGEX.match(address):

                ##if (isinstance(attachment,str) == False):
                ##if not attachment.filename == "":
                if attachFile == True:
                    filename = os.path.join(basedir + "/static/" + app.config['UPLOAD_FOLDER'], attachment.filename)

                    attachment.save(filename)


                msg = Message(subject)
                msg.sender = (fromName,fromEmail)
                msg.recipients = [address]

                msg.body = messageBody
                #if form.attachment.data is not str:
                #if not attachment.filename == "":   
                #if (isinstance(attachment,str) == False):

                if attachFile == True:
                newFileName = attachment.filename
                    with app.open_resource(filename) as fp:

                        msg.attach(
                            newFileName,
                            "application/octet-stream",
                            fp.read())

                mail.send(msg)

                success.append(address)



            else:
                failure.append(address)
                print("Failed:" + address)    

    else: 
        """Renders index page."""
        return render_template(
            'mailer/mailer.html',
        form = form
    )

    ##
    ## Successfully emailed, time to nuke the temp attachment
    ##
    os.system('rm ' + basedir + "/static/" + app.config['UPLOAD_FOLDER'] + "/'" + newFileName + "'")

    ##
    ##
    ##
    return render_template(
            'mailer/mailerCompleted.html',
            form = form,
            success = success,
            failure = failure
        )

FileRequired() 添加到验证器:

from flask_wtf.file import FileField, FileRequired
...
attachment = FileField('attachment' , validators=[FileRequired()])

需要文件,如果不提交文件,表单将无法验证。

编辑:

如果您希望文件是可选的,请删除 validators=[FileRequired()] 并检查文件是否已通过:

if form.attachment.data is None:
    print("File is empty")
    #  Code if file is empty
else:
    #  Code if file is passed

你也可以使用not:

if not form.attachment.data:
    print('no files has been uploaded')
当 A 为空或 None.

时,

not Atrue

所以,它在没有附加文件时触发(form.attachment.data == None)

使用 Flask-WTF==0.14.3,wtforms==2.3.3

is None 测试无效。 =='' 测试有效。

使用 FileField 的表单定义

class ProfileForm(FlaskForm):
    # other fields
    photo = FileField('Profile photo')

提交表单时

def profile():
    form = ProfileForm()
    if form.validate_on_submit():
        print('form.photo.data: [{}]'.format(form.photo.data))
        print('is None test: [{}]'.format(form.photo.data is None))
        print('==\'\' test: [{}]'.format(form.photo.data == ''))

        if form.photo.data is None:
            # will NOT work
            flash('you should upload a profile photo')

        if form.photo.data == '':
            # will work
            flash('profile photo is highly recommended')

    return render_template('profile.html', form=form)