marshmallow关系处理

  • Nesting Schemas

当模型间拥有关系,比如外键,schema如何处理呢?例如:blog和user之间的关系

 1 class User(object):
 2     def __init__(self, name, email):
 3         self.name = name
 4         self.email = email
 5         self.created_at = dt.datetime.now()
 6         self.friends = []
 7         self.employer = None
 8 
 9 class Blog(object):
10     def __init__(self, title, author):
11         self.title = title
12         self.author = author

使用Nested字段来代表关系,并传入相应的schema类

 1 from marshmallow import Schema, fields
 2 
 3 class UserSchema(Schema):
 4     name = fields.String()
 5     email = fields.Email()
 6     created_at = fields.DateTime()
 7 
 8 class BlogSchema(Schema):
 9     title = fields.String()
10     author = fields.Nested(UserSchema)

序列化blog对象则会嵌入user描述

 1 from marshmallow import Schema, fields, pprint
 2 
 3 user = User2(name="Monty", email="monty@python.org")
 4 blog = Blog(title="Something Completely Different", author=user)
 5 pprint(BlogSchema().dump(blog))
 6 
 7 {'author': {'created_at': '2019-11-14T15:28:09.212278',
 8             'email': 'monty@python.org',
 9             'name': 'Monty'},
10  'title': 'Something Completely Different'}

注意:如果field是多个嵌入对象的集合,则必须设置many=True

collaborators = fields.Nested(UserSchema, many=True)
  • Specifying Which Fields to Nest

如果想指定序列化时嵌入对象的某几个字段,可以设置only参数

 1 class BlogSchema(Schema):
 2     title = fields.String()
 3     author = fields.Nested(UserSchema, only=["email"])
 4 
 5 user = User(name="Monty", email="monty@python.org")
 6 blog = Blog(title="Something Completely Different", author=user)
 7 pprint(BlogSchema().dump(blog))
 8 
 9 {'author': {'email': 'monty@python.org'},
10  'title': 'Something Completely Different'}

如果有更深度的嵌套,可以使用“.”符号连接

 1 class Site(object):
 2     def __init__(self, blog):
 3         self.blog = blog
 4 
 5 class SiteSchema(Schema):
 6     blog = fields.Nested(BlogSchema)
 7 
 8 user = User(name="Mike", email="mike@python.org")
 9 blog = Blog(title="something is wrong", author=user)
10 site = Site(blog=blog)
11 schema = SiteSchema(only=['blog.author.email'])
12 pprint(schema.dump(site))
13 
14 {'blog': {'author': {'email': 'mike@python.org'}}}

使用Pluck字段可以用单个值来替换嵌套的数据

 1 class UserSchema(Schema):
 2     name = fields.String()
 3     email = fields.Email()
 4     friends = fields.Pluck("self", "name", many=True)
 5 
 6 user1 = User(name="Mike", email="mike@example.com")
 7 user2 = User(name="Tom", email="tom@example.com")
 8 user3 = User(name="Steve", email="steve@example.com")
 9 user3.friends = [user1, user2]
10 pprint(UserSchema().dump(user3))
11 
12 {'email': 'steve@example.com', 'friends': ['Mike', 'Tom'], 'name': 'Steve'}
13 
14 data = {
15         "name": "Steve",
16         "email": "steve@example.com",
17         "friends": [
18             "Tom",
19             "Mike"
20         ]
21 }
22 pprint(UserSchema().load(data))
23 
24 {'email': 'steve@example.com',
25  'friends': [{'name': 'Tom'}, {'name': 'Mike'}],
26  'name': 'Steve'}

也可以使用exclude参数来排除不要的字段,对于深度嵌套,同样可以使用“.”符号连接

  • Partial Loading

反序列化时,嵌套的schemas也可以继承父类的partial参数

 1 class UserSchemaStrict(Schema):
 2     name = fields.String(required=True)
 3     email = fields.Email()
 4     created_at = fields.DateTime(required=True)
 5 
 6 class BlogSchemaStrict(Schema):
 7     title = fields.String(required=True)
 8     author = fields.Nested(UserSchemaStrict, required=True)
 9 
10 schema = BlogSchemaStrict()
11 blog = {"title": "Something Completely Different", "author": {}}
12 result = schema.load(blog, partial=True)
13 pprint(result)
14 
15 {'author': {}, 'title': 'Something Completely Different'}

同样可以通过“.”符号连接来指定partial字段的子集

1 author = {"name": "Monty", "email": "monty@example.com"}
2 blog = {"title": "Something Completely Different", "author": author}
3 result = schema.load(blog, partial=("title", "author.created_at"))
4 pprint(result)
5 
6 {'author': {'email': 'monty@example.com', 'name': 'Monty'},
7  'title': 'Something Completely Different'}
  • Two-way Nesting

如果两个对象相互嵌套,则Nested可以传入类名的字符串形式,这允许在未定义该类时定义一个嵌套的schema类

 1 class Author(object):
 2     def __init__(self, name, email):
 3         self.name = name
 4         self.email = email
 5         self.books = []
 6 
 7 class Book(object):
 8     def __init__(self, title, author):
 9         self.title = title
10         self.author = author
11 
12 class AuthorSchema(Schema):
13     name = fields.Str()
14     email = fields.Email()
15     # Make sure to use the 'only' or 'exclude' params
16     # to avoid infinite recursion
17     books = fields.Nested('BookSchema', many=True, exclude=('author',))
18 
19     class Meta:
20         fields = ('name', 'email', 'books')
21 
22 class BookSchema(Schema):
23     title = fields.Str()
24     author = fields.Nested(AuthorSchema, only=('name', 'email'))
25 
26     class Meta:
27         fields = ('title', 'author')
28 
29 author = Author(name="Mike", email="mike@yooh.com")
30 book = Book(title="This is a joke", author=author)
31 pprint(BookSchema().dump(book))
32 
33 {'author': {'email': 'mike@yooh.com', 'name': 'Mike'},
34  'title': 'This is a joke'}
35 
36 author.books = [book]
37 pprint(AuthorSchema().dump(author))
38 
39 {'books': [{'title': 'This is a joke'}],
40  'email': 'mike@yooh.com',
41  'name': 'Mike'}
42 
  • Nesting A Schema Within Itself

如果需要自引用,则Nested传入‘self’即可

 1 class UserSchema(Schema):
 2     name = fields.String()
 3     email = fields.Email()
 4     friends = fields.Nested("self", many=True)
 5     # Use the 'exclude' argument to avoid infinite recursion
 6     employer = fields.Nested("self", exclude=("employer",), default=None)
 7 
 8 user = User("Steve", "steve@example.com")
 9 user.friends.append(User("Mike", "mike@example.com"))
10 user.friends.append(User("Joe", "joe@example.com"))
11 user.employer = User("Dirk", "dirk@example.com")
12 result = UserSchema().dump(user)
13 pprint(result, indent=2)
14 
15 # {
16 #     "name": "Steve",
17 #     "email": "steve@example.com",
18 #     "friends": [
19 #         {
20 #             "name": "Mike",
21 #             "email": "mike@example.com",
22 #             "friends": [],
23 #             "employer": null
24 #         },
25 #         {
26 #             "name": "Joe",
27 #             "email": "joe@example.com",
28 #             "friends": [],
29 #             "employer": null
30 #         }
31 #     ],
32 #     "employer": {
33 #         "name": "Dirk",
34 #         "email": "dirk@example.com",
35 #         "friends": []
36 #     }
37 # }

 

posted @ 2019-11-14 17:32  dowi  阅读(600)  评论(0编辑  收藏  举报