From c02bda429983e5461a65a5ec4cab2b29420ace52 Mon Sep 17 00:00:00 2001 From: Gyanu Date: Fri, 28 Aug 2026 09:34:59 +0530 Subject: [PATCH] Treat empty uploads as None when File(allow_none=True). Empty strings, JSON null, and FileStorage without a filename were rejected even though allow_none was set. --- CHANGELOG.rst | 8 ++++++++ src/flask_marshmallow/fields.py | 9 ++++++++- tests/test_fields.py | 9 +++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e5c9481..2702b40 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,14 @@ Changelog ========= +Unreleased +********** + +Bug fixes: + +* Treat empty or missing uploads as ``None`` when ``File(allow_none=True)`` + (:issue:`319`). + 1.5.0 (2026-04-15) ****************** diff --git a/src/flask_marshmallow/fields.py b/src/flask_marshmallow/fields.py index 1b6c53b..e8af15f 100755 --- a/src/flask_marshmallow/fields.py +++ b/src/flask_marshmallow/fields.py @@ -233,7 +233,14 @@ def deserialize( data: typing.Mapping[str, typing.Any] | None = None, **kwargs, ): - if isinstance(value, Sequence) and len(value) == 0: + from werkzeug.datastructures import FileStorage + + if self.allow_none: + if isinstance(value, str) and value in ("", "null"): + value = None + elif isinstance(value, FileStorage) and not value.filename: + value = None + elif isinstance(value, Sequence) and len(value) == 0: value = missing return super().deserialize(value, attr, data, **kwargs) diff --git a/tests/test_fields.py b/tests/test_fields.py index e399a02..0acfd78 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -168,6 +168,15 @@ def test_file_field(ma, mockauthor): field.deserialize("123", mockauthor) +def test_file_field_allow_none(ma): + field = ma.File(allow_none=True) + assert field.deserialize(None) is None + assert field.deserialize("") is None + assert field.deserialize("null") is None + empty = FileStorage(io.BytesIO(b""), "") + assert field.deserialize(empty) is None + + def test_config_field(ma, app, mockauthor): app.config["NAME"] = "test" field = ma.Config(key="NAME")