[Flask-WTF]MultiFileFieldでFileAllowedが効かない問題

Python

概要

  • MultiFileFieldのvalidatorsにFileAllowedを設定してもvalidatorとして機能しない。

原因

  • FileAllowedは複数のファイルに対して使用できるようになっていない。

解決

  • この解決方法に到達するために、1日かかってしまった。。。
NG
wtforms.fields.MultipleFileField('ファイル入力',validators=[
        DataRequired(),
        FileAllowed(['csv']) # これが効かない
    ])
OK
  • 独自のvalidatorクラスを用意して、MultiFileFieldのvalidatorsとして入れることで動作させる。
class MultiFileAllowed(object):
    """MultiFileFieldのためのFileAllowed自作クラス
    https://stackoverflow.com/questions/54700464/flask-wtf-passes-validation-when-it-should-fail

    """
    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(
                    '{extensions}以外許可されていません。: {extensions}'
                ).format(extensions=', '.join(self.upload_set)))

            if not self.upload_set.file_allowed(field.data, filename):
                raise StopValidation(self.message or field.gettext(
                    '許可された拡張子ではありません。'
                ))

# 上作成したクラスを独自のvalodatorとして使用する。
wtforms.fields.MultipleFileField('ファイル入力',validators=[
        DataRequired(),
        # FileRequired(),
        MultiFileAllowed(['csv'])
    ])

参考

Flask-WTF Passes Validation when it Should Fail
I have a Flask App that passes user input validation when it should fail. I have similar code in another part of the app that works just fine. It seems like the...

コメント

タイトルとURLをコピーしました