项目示例代码github地址:https://github.com/jinjidejuren/drf_learn
django rest framework序列化在其他的章节中进行了讲解,如果我们需要进行嵌套序列化,则需要对序列化类进行扩展,需要结合具体的需求进行设计。例如在设备这个模型的序列化类中,我们不仅需要获取服务器的信息,还想要获取设备所在机柜的信息。
class DeviceSerializer(serializers.ModelSerializer):
"""
设备序列化
"""
cabinet = serializers.SerializerMethodField()
def get_cabinet(self, obj):
cabinets = Cabinet.objects.filter(id=obj.cabinet_id)
if cabinets is not None and len(cabinets) > 0:
return CabinetSerializer(cabinets[0]).data
else:
return ""
class Meta:
model = Device
fields = ('id', 'device_name', 'device_type', 'brand', 'model',
'hardware', 'cabinet_id', 'cabinet', 'created_time', 'modified_time')
对于设备的序列化,我们在fields中添加了cabinet的信息,这个不是Device中原有的字段信息。额外添加需要进行定义。
cabinet = serializers.SerializerMethodField()
一旦定义了cabinet为SerializerMethodField,需要定义cabinet的获取方法。SerializerMethodField默认为我们提供了一个方法的名称method_name
def bind(self, field_name, parent):
# In order to enforce a consistent style, we error if a redundant
# 'method_name' argument has been used. For example:
# my_field = serializer.SerializerMethodField(method_name='get_my_field')
default_method_name = 'get_{field_name}'.format(field_name=field_name)
assert self.method_name != default_method_name, (
"It is redundant to specify `%s` on SerializerMethodField '%s' in "
"serializer '%s', because it is the same as the default method name. "
"Remove the `method_name` argument." %
(self.method_name, field_name, parent.__class__.__name__)
)
其中method_name需要满足名称为’get_{field_name}’.format(field_name=field_name),所以cabinet对应的获取方法为get_cabinet:
def get_cabinet(self, obj):
cabinets = Cabinet.objects.filter(id=obj.cabinet_id)
if cabinets is not None and len(cabinets) > 0:
return CabinetSerializer(cabinets[0]).data
else:
return ""
接着访问http://127.0.0.1:8060/assets/v1/devices/,可以得到device的信息以及device对应的cabinet信息:
GET /assets/v1/devices/
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"count": 3,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"device_name": "test-device1",
"device_type": "storage",
"brand": "dell",
"model": "HPE Apollo 4200 Gen9",
"hardware": "test-device1 hardware info",
"cabinet_id": 1,
"cabinet": {
"id": 1,
"cabinet_name": "first-cabinet",
"cabinet_code": "1",
"room_id": 1,
"created_time": "2018-07-10T13:05:46.155102Z",
"modified_time": null
},
"created_time": "2018-07-10T13:04:48.677079Z",
"modified_time": null
},
{
"id": 2,
"device_name": "test-device2",
"device_type": "storage",
"brand": "dell",
"model": "HPE Apollo 4200 Gen9",
"hardware": "test-device2 hardware info",
"cabinet_id": 2,
"cabinet": {
"id": 2,
"cabinet_name": "second-cabinet",
"cabinet_code": "2",
"room_id": 1,
"created_time": "2018-07-10T13:05:57.101426Z",
"modified_time": null
},
"created_time": "2018-07-10T13:05:01.953900Z",
"modified_time": null
},
{
"id": 3,
"device_name": "test-device3",
"device_type": "safe",
"brand": "dell",
"model": "HPE Apollo 4200 Gen9",
"hardware": "test-device3 hardware info",
"cabinet_id": 1,
"cabinet": {
"id": 1,
"cabinet_name": "first-cabinet",
"cabinet_code": "1",
"room_id": 1,
"created_time": "2018-07-10T13:05:46.155102Z",
"modified_time": null
},
"created_time": "2018-07-10T13:05:14.653610Z",
"modified_time": null
}
]
}
cabinet只是说明了嵌套序列化的方法,在实际应用中可以根据需求进行更多的嵌套序列化。