Search code examples
pythonmarshmallow

Define fields programmatically in Marshmallow Schema


Say I have a Schema like this:

class MySchema(Schema):

    field_1 = Float()
    field_2 = Float()
    ...
    field_42 = Float()

Is there a way to add those fields programmatically to the class?

Something like this:

class MyClass(BaseClass):

    FIELDS = ('field_1', 'field_2',..., 'field_42')

    for field in FIELDS:
        setattr(?, field, Float())  # What do I replace this "?" with?

I've seen posts about adding attributes dynamically to class instances, but this is different because

  • I don't want to patch an instance but a class
  • Marshmallow Schema uses a custom metaclass

The same question might apply to other model definition libraries, like ODM/ORM (uMongo/MongoEngine, SQL Alchemy,...)


Solution

  • All you need to do is to use type() function to build your class with any attributes you want:

    MySchema = type('MySchema', (marshmallow.Schema,), {
        attr: marshmallow.fields.Float()
        for attr in FIELDS
    })
    

    You can even have different types of fields there:

    fields = {}
    fields['foo'] = marshmallow.fields.Float()
    fields['bar'] = marshmallow.fields.String()
    MySchema = type('MySchema', (marshmallow.Schema,), fields)
    

    or as a base for your customizations:

    class MySchema(type('_MySchema', (marshmallow.Schema,), fields)):
        @marshmallow.post_dump
        def update_something(self, data):
            pass