假设我有这样一个模式:
class MySchema(Schema):
field_1 = Float()
field_2 = Float()
...
field_42 = Float()有办法以编程方式将这些字段添加到类中吗?
就像这样:
class MyClass(BaseClass):
FIELDS = ('field_1', 'field_2',..., 'field_42')
for field in FIELDS:
setattr(?, field, Float()) # What do I replace this "?" with?我看过关于向类实例动态添加属性的文章,但是这是不同的,因为
同样的问题可能也适用于其他模型定义库,如ODM/ORM (uMongo/MongoEngine,SQL Alchemy,.)
发布于 2017-02-15 01:36:23
您所需要做的就是使用type()函数来使用您想要的任何属性构建类:
MySchema = type('MySchema', (marshmallow.Schema,), {
attr: marshmallow.fields.Float()
for attr in FIELDS
})您甚至可以在那里有不同类型的字段:
fields = {}
fields['foo'] = marshmallow.fields.Float()
fields['bar'] = marshmallow.fields.String()
MySchema = type('MySchema', (marshmallow.Schema,), fields)或者作为自定义的基础:
class MySchema(type('_MySchema', (marshmallow.Schema,), fields)):
@marshmallow.post_dump
def update_something(self, data):
pass发布于 2017-02-14 16:29:44
通过对默认元类进行子类处理,我成功地做到了这一点:
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({field: 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及其args/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库。
发布于 2019-01-31 19:38:37
类Meta范例允许您指定要序列化的属性。棉花糖将根据属性的类型选择适当的字段类型。
class MySchema(Schema):
class Meta:
fields = ('field_1', 'field_2', ..., 'field_42')
...https://stackoverflow.com/questions/42231334
复制相似问题