Мне удалось сделать это, создав подкласс метакласса по умолчанию:
class MySchemaMeta(SchemaMeta):
@classmethod
def get_declared_fields(mcs, klass, cls_fields, inherited_fields, dict_cls):
fields = super().get_declared_fields(klass, cls_fields, inherited_fields, dict_cls)
FIELDS = ('field_1', 'field_2',..., 'field_42')
for field in FIELDS:
fields.update({fluid: Float()})
return fields
class MySchema(Schema, metaclass=MySchemaMeta):
class Meta:
strict = True
Я сделал это более общим:
class DynamicSchemaOpts(SchemaOpts):
def __init__(self, meta):
super().__init__(meta)
self.auto_fields = getattr(meta, 'auto_fields', [])
class DynamicSchemaMeta(SchemaMeta):
@classmethod
def get_declared_fields(mcs, klass, cls_fields, inherited_fields, dict_cls):
fields = super().get_declared_fields(klass, cls_fields, inherited_fields, dict_cls)
for auto_field_list in klass.opts.auto_fields:
field_names, field = auto_field_list
field_cls = field['cls']
field_args = field.get('args', [])
field_kwargs = field.get('kwargs', {})
for field_name in field_names:
fields.update({field_name: field_cls(*field_args, **field_kwargs)})
return fields
class MySchema(Schema, metaclass=DynamicSchemaMeta):
OPTIONS_CLASS = DynamicSchemaOpts
class Meta:
strict = True
auto_fields = [
(FIELDS,
{'cls': Float}),
]
я не писал
class Meta:
strict = True
auto_fields = [
(FIELDS, Float()),
]
потому что тогда все эти поля будут иметь один и тот же экземпляр Field
.
Field
и его аргументы/kwargs должны быть указаны отдельно:
class Meta:
strict = True
auto_fields = [
(FIELDS,
{'cls': Nested,
'args': (MyEmbeddedSchema),
'kwargs': {'required': True}
}),
]
У меня нет ни одного примера неудачного использования из-за того, что несколько полей используют один и тот же экземпляр, но это не кажется безопасным. Если эта предосторожность бесполезна, код можно упростить и сделать более читабельным:
class Meta:
strict = True
auto_fields = [
(FIELDS, Nested(MyEmbeddedSchema, required=True)),
]
Очевидно, что этот ответ специфичен для Marshmallow и не применяется к другим библиотекам ODM/ORM.
person
Jérôme
schedule
14.02.2017