How to accept None for String type field when using Flask-RESTPlus

Question:


I am just starting develop with flask-restplus and I am not a native speaker,

but I will try to describe my question as clear as I can.

I know there is a fields module in flask that help us define and filter response data type,

such as String, Integer, List and so on.

Is there any way to allow NULL / None when using fields module?

the following is my code that using field module to catch the value,

add_group = api.model(
        "add_group",
        {"team_groups": fields.List(fields.Nested(api.model("team_groups", {
            "name": fields.String(example="chicago bulls", description="name of add group"),
            "display_name": fields.String(example="bulls", description="display name of add group")})))})

and if the data type of display_name is not String, there would be the following error raised,

{
    "errors": {
        "team_groups.0.display_name": "123 is not of type 'string'"
    },
    "message": "Input payload validation failed"
}

what I want is when entering display_name, I can enter bulls or None


It seems few of the reference data / questions can be found, and I only found one result related

to my question, but eventually converting as non-null value to solve the issue.

if there is any part of my question not much clear,

please let me know, thank you.

the following is my develop environment:

flask-restplus 0.13.0
Python 3.7.4
postman 7.18.1


The following is my updated code:

from flask_restplus import Namespace, fields

class NullableString(fields.String):
    __schema_type__ = ['string', 'null']
    __schema_example__ = 'nullable string'

class DeviceGroupDto:
    api = Namespace("device/group", description="device groups")
    header = api.parser().add_argument("Authorization", location="headers", help="Bearer ")

    get_detail_group = api.model(
        "getdetail",
        {"team_groups": fields.List(fields.String(required=True,
                                                  description="team group id to get detail", example=1))})

    add_group = api.model(
        "add_group",
        {"team_groups": fields.List(fields.Nested(api.model("team_groups", {
            "name": fields.String(example="chicago bulls", description="name of add group"),
            "display_name": NullableString(attribute='a')})))})

if I input the following payload: (by postman)

{
    "team_groups": [
        {
            "name": "chicago bulls",
            "display_name": null
        }
    ]
}

It still returns:

{
    "errors": {
        "team_groups.0.display_name": "None is not of type 'string'"
    },
    "message": "Input payload validation failed"
}
Asked By: Roy Kuo

||

Answers:

if some of your fields are optional then make required=False

add_group = api.model(
        "add_group",
        {"team_groups": fields.List(fields.Nested(api.model("team_groups", {
            "name": fields.String(example="chicago bulls", description="name of add group"),
            "display_name": fields.String(example="bulls", description="display name of add group", required=False)})))})
Answered By: Sanjay

Yes, you can create a child class and use it instead of default ones, which will accept None as well

class NullableString(fields.String):
    __schema_type__ = ['string', 'null']
    __schema_example__ = 'nullable string'

So your code will look like

{ "property": NullableString(attribute=value)}

Additionally you can visit the issue github.com/noirbizarre/flask-restplus/issues/179

Answered By: Aqib

Here’s slightly evolved approach that I use. It lets you have fields of any type as nullable.

def nullable(fld, *args, **kwargs):
    """Makes any field nullable."""

    class NullableField(fld):
        """Nullable wrapper."""

        __schema_type__ = [fld.__schema_type__, "null"]
        __schema_example__ = f"nullable {fld.__schema_type__}"

    return NullableField(*args, **kwargs)

employee = api.model(
  "Employee",
  {
    "office": nullable(fields.String),
    "photo_key": nullable(fields.String, required=True),
  },
)
Answered By: Aleksey Gureiev