Model Schema

Model 是一个包含 字段 的特殊 Schema,它用于声明具有属性的对象,字段 是以类属性的方式定义在 schema.Model 子类中。Model 的用法如下:

from django_oasis import schema

class Author(schema.Model):
    name = schema.String()

Model 嵌套

将一个 Model 作为字段嵌套在其它 Model 中很简单。因为字段是一个 Schema,而 Model 本身也是 Schema,所以直接嵌套即可。

class Author(schema.Model):
    name = schema.String()
    birthday = schema.Date()

class Book(schema.Model):
    title = schema.String()
    author = Author()

print(Book().deserialize({'title': '三体', 'author': {'name': '刘慈欣', 'birthday': '1963-06-23'}}))
{'title': '三体', 'author': {'name': '刘慈欣', 'birthday': datetime.date(1963, 6, 23)}}

字段

字段实际上也是一个 Schema 对象,只是当 Schema 对象作为 Model 的字段时,它便具备了字段的特性。下面将介绍字段的各种特性。

字段继承

如同 Python 的类属性继承,Model 的字段同样也可以继承给子 Model。

单继承示例: B Model 继承于 A Model。

class A(schema.Model):
    a = schema.String()

class B(A):
    b = schema.String()

print(B().deserialize({'a': 1, 'b': 2}))
{'a': '1', 'b': '2'}

多继承示例: C Model 同时继承 A Model 和 B Model。

class A(schema.Model):
    a = schema.String()

class B(schema.Model):
    b = schema.String()

class C(A, B):
    c = schema.String()

print(C().deserialize({'a': 1, 'b': 2, 'c': 3}))
{'a': '1', 'b': '2', 'c': '3'}

备注

多继承时,如果多个父类存在同名字段,则优先继承位于左侧的父类的字段。

class A1(schema.Model):
    a = schema.Integer()

class A2(schema.Model):
    a = schema.String()

class B1(A1, A2):
    ...

class B2(A2, A1):
    ...

value = {'a': 1}
print(B1().deserialize(value))
print(B2().deserialize(value))

输出结果为:

{'a': 1}
{'a': '1'}

字段命名要求

你可以使用任何有效的字段名,即使字段名和父类的某个方法名或者属性同名也不会导致错误。

虽然字段是以类属性的方式定义的,但字段并不会成为类属性,也就意味着无法通过 <model_name>.<field_name> 的形式访问到字段。

这样做的好处,就是不会出现同名污染,如下例字段名为 “deserialize”,这和 Schema.deserialize 方法同名,但这并不会有任何问题。

>>> class Foo(schema.Model):
...     deserialize = schema.Integer()

>>> Foo().deserialize({'deserialize': '1'})
{'deserialize': 1}

alias 和 attr

可以使用 alias 和 attr 参数为序列化和反序列化的两端指定不同的字段名映射。如果不指定,它们默认等于字段名。

它们之间的关系如下:

attr — serialize() —> alias

alias — deserialize() —> attr

示例:

>>> class Foo(schema.Model):
...     a = schema.Integer(alias='outside', attr='inside')

>>> Foo().serialize({'inside': '1'})
{'outside': 1}

>>> Foo().deserialize({'outside': '1'})
{'inside': 1}