Devourer
Devourer

Reputation: 33

Flask restx model nested wildcard dict

I was wondering if I'm only one struggling with such problem.

Lets take dict for example:

data = {'totalSize': 3000, 'freq': 2400,
        'distribution':
            {'ram1': {'size': 200, 'status': 'OK'},
             'ram2': {'size': 100, 'status': 'OK'}
             }
        }

Please not that ram1/2 is dynamic keys that can not be known in advance

Question, how should my api.model look like ? I have:

wild = {"*": fields.Wildcard(fields.String())}
hw_memory = api.model('Memory', {
    'totalSize': fields.Integer(description='total memory size in MB',
                                example=1024),
    'freq': fields.Integer(description='Speed of ram in mhz', example=800),
    'distribution': fields.Nested(wild),
})

It is working, however it does not validate anything below "distribution", in other words, works like wildcard, anything there will be accepted. Is there a way to nest dicts in such way having wildcard dynamic key ?

Upvotes: 3

Views: 4477

Answers (1)

Andrey Kurilin
Andrey Kurilin

Reputation: 124

First of all, Wildcard type of field accepts the definition of the dict values, not the definition of the keys, i.e fields.Wildcard(fields.String()) validates that dict values can be only of string type (in your case you need to provide definition of distribution).

The second mistake is that you are defining distribution field as Nested object instead of using Wilcard.

The following code should work for validation purpose:


DISTRIBUTION_MODEL = NAMESPACE.model("Distribution", dict(
    size=fields.Integer(),
    status=fields.String(),
))

MEMORY_MODEL = NAMESPACE.model("Memory", dict(
    totalSize=fields.Integer(description='total memory size in MB',
                             example=1024),
    freq=fields.Integer(description='Speed of ram in mhz', example=800),
    distribution=fields.Wildcard(fields.Nested(DISTRIBUTION_MODEL))
))

Unfortunately, it doesn't work for marshaling. The next code should work for marshaling, but doesn't for validation input payload:


OUTPUT_MEMORY_MODEL = NAMESPACE.model("OutputMemory", dict(
    totalSize=fields.Integer(description='total memory size in MB',
                             example=1024),
    freq=fields.Integer(description='Speed of ram in mhz', example=800),
    distribution=flask_utils.fields.Nested(
        NAMESPACE.model(
            "distributions", {
                "*": fields.Wildcard(
                    # DISTRIBUTION_MODEL is taken from previous snippet
                    fields.Nested(DISTRIBUTION_MODEL)
                )
            }
        )
    )
))

Upvotes: 1

Related Questions