marshmallow模式子类,根据sqlalchemy类自动定义字段
golden_marshmallows的Python项目详细描述
金色棉花糖
sqlalchemy和marshmallow的更好集成。把marshmallow
变成金子的一点炼金术。
安装
只需使用pip
:
$ pip install golden-marshmallows
用法
序列化
以这些sqlalchemy模型为例:
classWizardCollege(Base):__tablename__='wizard_college'id=Column(Integer,primary_key=True)name=Column(String)alchemists=relationship('Alchemist')def__repr__(self):return'<WizardCollege(name={self.name!r})>'.format(self=self)classAlchemist(Base):__tablename__='alchemists'id=Column(Integer,primary_key=True)name=Column(String)school_id=Column(Integer,ForeignKey('wizard_college.id'))formulae=relationship('Formula')def__repr__(self):return'<Alchemist(name={self.name!r})>'.format(self=self)classFormula(Base):__tablename__='forumulae'id=Column(Integer,primary_key=True)title=Column(String)author_id=Column(Integer,ForeignKey('alchemists.id'))def__repr__(self):return'<Formula(title={self.title!r})>'.format(self=self)
GoldenSchema
类允许快速轻松地生成可用于sqlalchemy对象序列化/反序列化的marshmallow
架构。只要在初始化时传递model类,就可以开始了:
importjsonfromgolden_marshmallow.schemaimportGoldenSchemafrommodelsimportAlchemist,Formula,WizardCollegealchemist=Alchemist(name='Albertus Magnus',school_id=1)session.add(alchemist)session.flush()schema=GoldenSchema(Alchemist)serialized=schema.dump(alchemist).dataprint(json.dump(serialized,indent=4))# { # "id": 1,# "name": "Albertus Magnus",# "school_id": 1# }
就这样!不需要定义您自己的Schema
子类,除非您真的想(下面有更多内容)。
嵌套对象
但是这个炼金术士的公式呢?通过将包含嵌套对象的每个字段映射到相关的sqlalchemy类,可以很容易地将嵌套对象添加到mix中:
nested_map={'formulae':{'class':Formula,'many':True}}formula=Formula(title='transmutation')alchemist.formulae.append(formula)session.commit()schema=GoldenSchema(Alchemist,nested_map=nested_map)serialized=schema.dump(alchemist).dataprint(json.dump(serialized,indent=4))# {# "id": 1,# "name": "Albertus Magnus",# "school_id": 1,# "formulae" : [# {# "title": "transmutation"# }# ]# }
实际上,GoldenSchema
类以这种方式支持任意嵌套,只需根据需要调整映射即可:
nested_map={'alchemists':{'class':Alchemist,'many':True,'nested_map':{'formulae':{'class':Formula,'many':True}}}}college=WizardCollege(name='Bogwarts')college.alchemists.append(alchemist)session.add(college)session.flush()schema=GoldenSchema(WizardCollege,nested_map=nested_map)serialized=schema.dump(college).dataprint(json.dump(serialized,indent=4))# {# "id": 1,# "name": "Bogwarts",# "alchemists": [# {# "id": 1,# "school_id": 1,# "name": "Albertus Magnus",# "formulae": [# {# "title": "transmutation",# "author_id": 1,# "id": 1# }# ]# }# ]# }
反序列化
当然,您也可以将数据反序列化为sqlalchemy对象,这同样简单:
# Start at the end of the last example and work backwardsdata={"id":1,"name":"Bogwarts","alchemists":[{"formulae":[{"title":"transmutation","author_id":1,"id":1}],"school_id":1,"id":1,"name":"Albertus Magnus"}]}college=schema.load(data).dataprint(college)# <WizardCollege(name='Bogwarts')>print(college.alchemists)# [<Alchemist(name='Albertus Magnus')>]print(college.alchemists[0].formulae)# [<Formula(title='transmutation')>]
额外功能
骆驼壳/蛇壳
snake_to_camel
标志允许serde到/从camelcase,例如,当将python数据序列化为json以作为api响应发送时:
# `Formula.author_id` is easily converted to camelCaseschema=GoldenSchema(Formula,snake_to_camel=True)serialized=schema.dump(formula).dataprint(json.dumps(serialized,indent=4))# Notice `author_id` has become `authorId`# {# "title": "transmutation",# "authorId": 1,# "id": 1# }
相同的GoldenSchema
实例,当用于load
(反序列化)数据时,将期望camelcased属性并将其作为snake外壳属性加载:
data={"title":"transmutation","authorId":1,"id":1}formula=schema.load(data).dataprint(formula.author_id)# 1
还包括具有相反行为的标志camel_to_snake
。
此功能也适用于手动声明的字段;也就是说,您自己在子类化GoldenSchema
时声明的字段,就像这样:
classMySchema(GoldenSchema):manually_declared=fields.Function(lambdaobj:'my special value')my_schema=MySchema(Formula,snake_to_camel=True)serialized=schema.dump(formula).dataprint(json.dumps(serialized,indent=4))# `manually_declared` has become camelCase# {# "title": "transmutation",# "authorId": 1,# "id": 1,# "manuallyDeclared": "my special value"# }
实际上,您可以使用这个特性而不涉及sqlalchemy;只需使用CaseChangingSchema
,即GoldenSchema
的父类:
fromgolden_marshmallows.schemaimportCaseChangingSchemaclassSnakeSchema(CaseChangingSchema):attr_one=fields.String()attr_two=fields.Integer()classSnakeObj:def__init__(self,attr_one,attr_two):self.attr_one=attr_oneself.attr_two=attr_twoschema=SnakeSchema(snake_to_camel=True)obj=SnakeObj('field1',2)serialized=schema.dump(obj).dataprint(json.dumps(serialized,indent=4))# {# 'attrOne': 'field1',# 'attrTwo': 2# }
复制对象
作为一个小方便,您可以在初始化时传递new_obj
标志,以指示在反序列化期间应忽略名为id
的任何字段:
schema=GoldenSchema(Formula,snake_to_camel=True,new_obj=True)data={"title":"transmutation","authorId":1,"id":1}new_formula=schema.load(data).dataprint(new_formula.title)# 'transmutation'print(new_formula.id)# None<>这允许您快速地将现有对象的数据表示反序列化为新的副本。