schema能夠嵌套使用以表示對象間的關係(如外鍵關係)。python
例以下例中Blog有一個用User對象表示的author屬性:app
import datetime as dt class User(object): def __init__(self, name, email): self.name = name self.email = email self.created_at = dt.datetime.now() self.friends = [] self.employer = None class Blog(object): def __init__(self, title, author): self.title = title self.author = author # A User object
使用Nested
子類接收嵌套的schema表示兩者的關係:code
from marshmallow import Schema, fields, pprint class UserSchema(Schema): name = fields.String() email = fields.Email() created_at = fields.DateTime() class BlogSchema(Schema): title = fields.String() author = fields.Nested(UserSchema)
序列化後的blog對象將包含嵌套的user對象:對象
user = User(name="Monty", email="monty@python.org") blog = Blog(title="Something Completely Different", author=user) result = BlogSchema().dump(blog) pprint(result) # {'title': u'Something Completely Different', # 'author': {'name': u'Monty', # 'email': u'monty@python.org', # 'created_at': '2014-08-17T14:58:57.600623+00:00'}}
若是field嵌套對象是一個集合,必須設置many=True
,如collaborators = fields.Nested(UserSchema, many=True)
blog
設置only
參數顯式地指定對嵌套對象的哪些屬性進行序列化:遞歸
class BlogSchema2(Schema): title = fields.String() author = fields.Nested(UserSchema, only=["email"]) schema = BlogSchema2() result = schema.dump(blog) pprint(result) # { # 'title': u'Something Completely Different', # 'author': {'email': u'monty@python.org'} # }
使用點分隔符能夠表示深層嵌套對象的屬性:字符串
class SiteSchema(Schema): blog = fields.Nested(BlogSchema2) schema = SiteSchema(only=['blog.author.email']) result, errors = schema.dump(site) pprint(result) # { # 'blog': { # 'author': {'email': u'monty@python.org'} # } # }
若是給only
參數傳遞的是字符串(上面的例子傳遞的是列表),將返回單個值(上面的例子返回的是鍵值映射)或值的列表(須要設置many=True
):it
class UserSchema(Schema): name = fields.String() email = fields.Email() friends = fields.Nested('self', only='name', many=True) # ... create ``user`` ... result, errors = UserSchema().dump(user) pprint(result) # { # "name": "Steve", # "email": "steve@example.com", # "friends": ["Mike", "Joe"] # }
對於兩個互相嵌套的對象,能夠使用類名引用嵌套的schema,即使是引用時該schema尚未被定義。io
在下面的例子中,Author和Book對象是一對多的關係:class
class AuthorSchema(Schema): # 必須使用only或exclude參數避免無限遞歸 books = fields.Nested('BookSchema', many=True, exclude=('author', )) class Meta: fields = ('id', 'name', 'books') class BookSchema(Schema): author = fields.Nested(AuthorSchema, only=('id', 'name')) class Meta: fields = ('id', 'title', 'author')
from marshmallow import pprint from mymodels import Author, Book author = Author(name='William Faulkner') book = Book(title='As I Lay Dying', author=author) book_result, errors = BookSchema().dump(book) pprint(book_result, indent=2) # { # "id": 124, # "title": "As I Lay Dying", # "author": { # "id": 8, # "name": "William Faulkner" # } # } author_result, errors = AuthorSchema().dump(author) pprint(author_result, indent=2) # { # "id": 8, # "name": "William Faulkner", # "books": [ # { # "id": 124, # "title": "As I Lay Dying" # } # ] # }
也能夠使用導入模塊的方式傳遞嵌套schema,如books = fields.Nested('path.to.BookSchema', many=True, exclude=('author', ))
給Nested傳遞字符串參數self
表示和對象自己的關係:
class UserSchema(Schema): name = fields.String() email = fields.Email() friends = fields.Nested('self', many=True) # Use the 'exclude' argument to avoid infinite recursion employer = fields.Nested('self', exclude=('employer', ), default=None) user = User("Steve", 'steve@example.com') user.friends.append(User("Mike", 'mike@example.com')) user.friends.append(User('Joe', 'joe@example.com')) user.employer = User('Dirk', 'dirk@example.com') result = UserSchema().dump(user) pprint(result.data, indent=2) # { # "name": "Steve", # "email": "steve@example.com", # "friends": [ # { # "name": "Mike", # "email": "mike@example.com", # "friends": [], # "employer": null # }, # { # "name": "Joe", # "email": "joe@example.com", # "friends": [], # "employer": null # } # ], # "employer": { # "name": "Dirk", # "email": "dirk@example.com", # "friends": [] # } # }