第二章 View的编写
前言
基于 ModelViewSet 来写各个试图, 编写逻辑按照Mode开始.
TableClassify
这个表就是前面将到的分类表, 也是整个项目的入口.
这个表基本上是比较简单的, 此表设计为二级表, 即有主分类, 主分类下才是真正实际应用的表.如下图
新增数据
新增数据主要关注 PID 字段, 如果上传 PID 则 PID 必须是存在的且它的 PID 为 Null.
- API_URL
-
http://127.0.0.1:8000/api/v1/cmdb/table-classify/
-
-
上传数据格式
-
{ "name": "服务器", "alias": "server", "remark": "服务器类型表主类", "pid": "" }
-
- 数据返回
1 { 2 "code": 0, 3 "data": { 4 "id": 1, 5 "create_time": "2021-05-24 19:08:20", 6 "update_time": "2021-05-24 19:08:20", 7 "remark": "服务器类型表主类", 8 "is_deleted": false, 9 "name": "服务器", 10 "alias": "server", 11 "is_forbid_bind": false, 12 "pid": null 13 }, 14 "message": null 15 }
- 试图代码
1 def create(self, request, *args, **kwargs): 2 data = request.data 3 pid = data.get('pid') 4 5 # 如果新建数据存在PID 6 if pid: 7 8 # 查询 id = pid 的实例, 如果实例的PID不为Null则返回错误 9 if OperateInstance.get_table_classify(data['pid']).pid: 10 return json_error_response(f'指定的pid:({data["pid"]}) 不是主类型模型表.') 11 return super(TableClassifyViewSet, self).create(request, *args, **kwargs)
修改数据
新增数据主要关注 PID 字段,
- 如果 修改的数据为主类型, 则需要判断此表下有没有分类表, 如果有则禁止修改.
- 判断要修改的目标PID是否为主类型表, 判断方法, 取到 id = pid 的实例, 实例.pid 为空则是主分类.
- API_URL
-
http://127.0.0.1:8000/api/v1/cmdb/table-classify/ID/
-
-
上传数据格式
-
{ "name": "服务器", "alias": "server", "remark": "服务器类型表主类", "pid": "" }
-
- 数据返回
1 { 2 "code": 0, 3 "data": { 4 "id": 4, 5 "create_time": "2021-05-24 19:15:20", 6 "update_time": "2021-05-24 19:16:12", 7 "remark": "物理机类型表", 8 "is_deleted": false, 9 "name": "物理网卡1", 10 "alias": "network", 11 "is_forbid_bind": false, 12 "pid": 1 13 }, 14 "message": null 15 }
- 试图代码
1 def update(self, request, *args, **kwargs): 2 instance = self.get_object() 3 pid = request.data.get('pid') 4 # 判断是否存在PID 5 if pid: 6 # 查询 pid = instance.id 的表, 如果存在则报错. 7 if OperateInstance.get_children_table_classify(instance.id): 8 return json_error_response('无法修改, 此类型表存在子分类表.') 9 # 获取要要指定为主类的实例, 并判断是否为主类 也就是 PID == Null 10 parent_table_classify = OperateInstance.get_table_classify(pid) 11 if not parent_table_classify or parent_table_classify.pid: 12 return json_error_response('指定的 pid 不存在或者不是主分类表.') 13 return super(TableClassifyViewSet, self).update(request, *args, **kwargs)
表关系绑定
表关系绑定这里用到了 TableRelation 表来确定绑定管理,
字段说明:
- TableClassify 的 is_forbid_bind, 这个值用来判断是否可以绑定, 如果设置为True, 其他的表就无法跟此表绑定.
- TableRelation 的 parent_table, 主表ID.
- TableRelation 的 child_table, 子表ID
-
TableRelation 的 is_foreign_key, 表示绑定之后数据的对应关系, 为True 则是一对多, 为 False 则是 一对一.
验证逻辑:
- 验证 上传的 parent_table_id 和 child_table_id 是否存在 TableClassify 实例. 并且不是 主分类表.
- 验证 parent_table_id 和 child_table_id 实例 is_forbid_bind 如果为 True 则禁止进行数据绑定.
- 验证 parent_table_id 和 child_table_id 实例 有没有自己的字段表, 如果没有禁止绑定, 这个规则可以删掉, 逻辑问题.
- URL
-
http://127.0.0.1:8000/api/v1/cmdb/table-classify/relation/
-
- 数据上传格式
1 { 2 "parent_table_id": 2, 3 "child_table_id": 3, 4 "is_foreign_key": false, 5 "is_forbid_bind": true 6 }
- 数据返回格式
{ "code": 0, "data": "关联成功", "message": null }
- 试图代码
1 @action(methods=['post'], detail=False) 2 def relation(self, request, *args, **kwargs): 3 data = request.data 4 parent_table_id = data['parent_table_id'] 5 child_table_id = data['child_table_id'] 6 if not parent_table_id or not child_table_id: 7 return json_error_response('parent_table_id and child_table_id 是必传参数.') 8 9 parent_classify = OperateInstance.get_table_classify(parent_table_id) 10 child_classify = OperateInstance.get_table_classify(child_table_id) 11 12 # 验证表是否存在 13 if not parent_classify or not child_classify: 14 return json_error_response('parent分类表或者child分类表不存在') 15 16 # 验证 有主分类表 17 if not parent_classify.pid or not child_classify.pid: 18 return json_error_response('parent分类表或者child分类表是主分类表, 不允许进行绑定操作.') 19 20 # 验证 是否禁止绑定. 21 if parent_classify.is_forbid_bind or child_classify.is_forbid_bind: 22 return json_error_response('parent分类表或者child分类表,禁止绑定操作.') 23 24 # 验证是否存在字段表 25 parent_field = OperateInstance.get_table_field(parent_table_id) 26 child_field = OperateInstance.get_table_field(child_table_id) 27 if not parent_field or not child_field: 28 return json_error_response('parent类型表或者child类型表没有字段表') 29 30 table_relation_obj = TableRelation.objects.create(parent_table_id=parent_table_id, 31 child_table_id=child_table_id, 32 is_foreign_key=data.get('is_foreign_key')) 33 table_relation_obj.save() 34 35 if request.data.get('is_forbid_bind'): 36 child_classify.is_forbid_bind = True 37 child_classify.save() 38 39 return json_ok_response('关联成功')
表关系解绑
- 验证逻辑
- 确定存在绑定记录
- 清理资产绑定记录
-
child_table is_forbid_bind 字段如果为True 修改为False.
- URL
-
http://127.0.0.1:8000/api/v1/cmdb/table-classify/un-relation/
-
- 上传数据格式
{ "parent_table_id": 2, "child_table_id": 7 }
- 数据返回格式
{ "code": 0, "data": "解除关联成功", "message": null }
- 试图代码
1 @action(methods=['post'], detail=False, url_path='un-relation') 2 def un_relation(self, request, *args, **kwargs): 3 data = request.data 4 5 parent_table_id = data['parent_table_id'] 6 child_table_id = data['child_table_id'] 7 if not parent_table_id or not child_table_id: 8 return json_error_response('parent_table_id and child_table_id 是必传参数.') 9 10 classify_relation_obj = OperateInstance.get_table_relation(parent_table_id, child_table_id) 11 if not classify_relation_obj: 12 return json_error_response( 13 f'找不到parent_table_id为:{parent_table_id}, child_table_id为: {child_table_id} 关系记录') 14 15 # 找到绑定资产记录并删除 16 asset_relation_all = OperateInstance.get_asset_relation(classify_relation_obj) 17 if asset_relation_all: 18 for instance in asset_relation_all: 19 instance.delete() 20 21 classify_relation_obj.delete() 22 23 # 修改 child_classify_obj 的值 24 child_classify_obj = OperateInstance.get_table_classify(child_table_id) 25 if child_classify_obj.is_forbid_bind: 26 child_classify_obj.is_forbid_bind = False 27 child_classify_obj.save() 28 29 return json_ok_response('解除关联成功')
删除数据
- 验证逻辑
- 无
- URL
-
http://127.0.0.1:8000/api/v1/cmdb/table-field/ | http://127.0.0.1:8000/api/v1/cmdb/table-field/ID/
-
- 上传数据格式
- 数据返回格式
- 试图代码
查询数据
- 验证逻辑
- 查看数据同时要返回字段表的 fields, rules
- URL
-
http://127.0.0.1:8000/api/v1/cmdb/table-classify/
-
- 数据返回格式
{ "code": 0, "data": [ { "id": 1, "create_time": "2021-05-24 19:08:20", "update_time": "2021-05-24 19:08:20", "remark": "服务器类型表主类", "is_deleted": false, "name": "服务器", "alias": "server", "is_forbid_bind": false, "pid": null, "fields": null, "rules": null }, { "id": 2, "create_time": "2021-05-24 19:14:25", "update_time": "2021-05-24 19:14:25", "remark": "物理机类型表", "is_deleted": false, "name": "物理机", "alias": "Physical", "is_forbid_bind": false, "pid": 1, "fields": { "board_sn": { "name": "主板SN号", "order": 5 }, "hostname": { "guid": true, "name": "主机名", "order": 0 }, "cpu_count": { "name": "逻辑CPU", "order": 5 }, "cpu_model": { "name": "cpu_型号", "order": 10 }, "manage_ip": { "name": "管理IP", "order": 1 }, "os_version": { "name": "系统版本", "order": 3 }, "board_model": { "name": "型号", "order": 7 }, "os_platform": { "name": "操作系统", "order": 2 }, "device_status": { "name": "设备状态", "order": 4 }, "board_manufacturer": { "name": "制造商", "order": 6 }, "cpu_physical_count": { "name": "物理CPU", "order": 6 } }, "rules": { "board_sn": { "lens": 64, "type": "Str" }, "hostname": { "lens": 46, "type": "Str", "unique": true, "not_null": false }, "cpu_count": { "max": 130, "min": 1, "type": "Int" }, "cpu_model": { "lens": 64, "type": "Str" }, "manage_ip": { "type": "IP", "prefix": "172.16.0.", "unique": true }, "os_version": { "lens": 64, "type": "Str" }, "board_model": { "lens": 64, "type": "Str" }, "os_platform": { "lens": 64, "type": "Str" }, "device_status": { "type": "Choice", "choice": [ "上线", "下线", "离线" ], "default": 0 }, "board_manufacturer": { "lens": 64, "type": "Str" }, "cpu_physical_count": { "max": 64, "min": 1, "type": "Int" } } }, { "id": 3, "create_time": "2021-05-24 19:15:05", "update_time": "2021-05-24 22:20:01", "remark": "物理机类型表", "is_deleted": false, "name": "物理磁盘", "alias": "disk", "is_forbid_bind": true, "pid": 1, "fields": { "slot": { "guid": true, "name": "槽位", "order": 0 }, "model": { "name": "型号", "order": 1 }, "pd_type": { "name": "类别", "order": 2 }, "capacity": { "name": "容量", "order": 2 } }, "rules": { "slot": { "lens": 64, "type": "Str", "unique": true }, "model": { "lens": 64, "type": "Str" }, "pd_type": { "lens": 64, "type": "Str" }, "capacity": { "lens": 64, "type": "Str" } } }, { "id": 4, "create_time": "2021-05-24 19:15:20", "update_time": "2021-05-24 22:23:05", "remark": "物理机类型表", "is_deleted": false, "name": "物理网卡", "alias": "network", "is_forbid_bind": true, "pid": 1, "fields": { "up": { "name": "网卡状态", "order": 5 }, "name": { "guid": true, "name": "网卡名", "order": 0 }, "hwaddr": { "name": "Mac地址", "order": 4 }, "ipaddr": { "name": "IP地址", "order": 1 }, "gateway": { "name": "网关", "order": 3 }, "network": { "name": "子网掩码", "order": 2 } }, "rules": { "up": { "lens": 64, "type": "Str" }, "name": { "lens": 46, "type": "Str", "unique": true }, "hwaddr": { "lens": 120, "type": "Str" }, "ipaddr": { "type": "IP", "unique": true, "not_null": true }, "gateway": { "type": "IP" }, "network": { "lens": 64, "type": "Str" } } }, { "id": 5, "create_time": "2021-05-24 22:06:59", "update_time": "2021-05-24 22:23:11", "remark": "存放物理机内存", "is_deleted": false, "name": "物理内存", "alias": "memory", "is_forbid_bind": true, "pid": 1, "fields": { "sn": { "name": "SN号", "order": 4 }, "slot": { "guid": true, "name": "槽位", "order": 0 }, "model": { "name": "型号", "order": 2 }, "speed": { "name": "速率", "order": 5 }, "capacity": { "name": "容量", "order": 3 }, "manufacturer": { "name": "制造商", "order": 1 } }, "rules": { "sn": { "lens": 64, "type": "Str" }, "slot": { "lens": 64, "type": "Str", "unique": true }, "model": { "lens": 64, "type": "Str" }, "speed": { "lens": 64, "type": "Str" }, "capacity": { "lens": 64, "type": "Str" }, "manufacturer": { "lens": 64, "type": "Str" } } }, { "id": 6, "create_time": "2021-05-24 22:08:53", "update_time": "2021-05-24 22:08:53", "remark": "存放通用记录", "is_deleted": false, "name": "通用类", "alias": "general", "is_forbid_bind": false, "pid": null, "fields": null, "rules": null }, { "id": 7, "create_time": "2021-05-24 22:09:25", "update_time": "2021-05-25 00:51:53", "remark": "设备资产标签", "is_deleted": false, "name": "标签", "alias": "label", "is_forbid_bind": false, "pid": 6, "fields": { "name": { "guid": true, "name": "标签名", "order": 0 } }, "rules": { "name": { "lens": 64, "type": "Str", "unique": true } } } ], "message": null }
- 无试图代码, serializers 代码如下
class TableClassifySerializer(serializers.ModelSerializer): class Meta: model = TableClassify fields = '__all__' def to_representation(self, instance): representation = super(TableClassifySerializer, self).to_representation(instance) representation['fields'] = TableFieldSerializer(instance.fields).data['fields'] if hasattr(instance, 'fields') else None representation['rules'] = TableFieldSerializer(instance.fields).data['rules'] if hasattr(instance, 'fields') else None return representation
TableField
字段表, 主要用于类型表的字段存储, 以及校验规则.
字段说明:
- fields 字段
1 "fields": { 2 "hostname": { 3 "name": "主机名", # key 字段, val 是中文, 前端展示以及后端校验使用. 4 "guid": true, # 全局唯一, 用来标识唯一Key的. 只可以出现一次 5 "order": 0 # 排序 ID, 前端使用 6 }, 7 "manage_ip": { 8 "name": "管理IP", 9 "order": 1 10 } 11 ... 12 }
- rules
1 "rules": { 2 "hostname": { # key 跟 fields 字段 key 一一对应. 3 "type": "Str", 4 "lens": 46, # 限制属性可选 5 "unique": true, # 如果 fields 中设置了全局唯一 key.必须这是 unique 为 True 6 "not_null": false 7 }, 8 "manage_ip": { 9 "type": "IP", 10 "unique": true, 11 "prefix": "172.16.0." 12 } 13 ... 14 }
现支持的类型及属性:
- 类型
-
["Str", "Int", "Choice", "IP"]
-
- 属性
-
["default", "unique", "not_null", "lens", "choice", "prefix", "max", "min"]
-
新增数据
- 验证逻辑
- 1. 如果分类表是主分类表禁止绑定.
- 2. 上传数据验证, 使用 check_fields
- URL
-
http://127.0.0.1:8000/api/v1/cmdb/table-field/
-
- 数据上传格式
{ "remark": "", "table_classify": 2, "fields": { "hostname": { "name": "主机名", "guid": true, "order": 0 }, "manage_ip": { "name": "管理IP", "order": 1 }, "os_platform": { "name": "操作系统", "order": 2 }, "os_version": { "name": "系统版本", "order": 3 }, "device_status": { "name": "设备状态", "order": 4 }, "cpu_count": { "name": "逻辑CPU", "order": 5 }, "cpu_physical_count": { "name": "物理CPU", "order": 6 }, "cpu_model":{ "name": "cpu_型号", "order": 10 }, "board_sn": { "name": "主板SN号", "order": 5 }, "board_manufacturer": { "name": "制造商", "order": 6 }, "board_model": { "name": "型号", "order": 7 } }, "rules": { "hostname": { "type": "Str", "lens": 46, "unique": true, "not_null": false }, "manage_ip": { "type": "IP", "unique": true, "prefix": "172.16.0." }, "os_platform": { "type": "Str", "lens": 64 }, "os_version": { "type": "Str", "lens": 64 }, "device_status": { "type": "Choice", "choice": ["上线", "下线", "离线"], "default": 0 }, "cpu_count": { "type": "Int", "max": 130, "min": 1 }, "cpu_physical_count": { "type": "Int", "max": 64, "min": 1 }, "cpu_model":{ "type": "Str", "lens": 64 }, "board_sn": { "type": "Str", "lens": 64 }, "board_manufacturer": { "type": "Str", "lens": 64 }, "board_model": { "type": "Str", "lens": 64 } } }
{ "remark": "", "table_classify": 4, "fields": { "name": { "name": "网卡名", "guid": true, "order": 0 }, "ipaddr": { "name": "IP地址", "order": 1 }, "network": { "name": "子网掩码", "order": 2 }, "gateway": { "name": "网关", "order": 3 }, "hwaddr": { "name": "Mac地址", "order": 4 }, "up": { "name": "网卡状态", "order": 5 } }, "rules": { "name": { "type": "Str", "lens": 46, "unique": true }, "ipaddr": { "type": "IP", "unique": true, "not_null": true }, "network": { "type": "Str", "lens": 64 }, "gateway": { "type": "IP" }, "hwaddr": { "type": "Str", "lens": 120 }, "up": { "type": "Str", "lens": 64 } } }
{ "remark": "", "table_classify": 3, "fields": { "slot": { "name": "槽位", "guid": true, "order": 0 }, "model": { "name": "型号", "order": 1 }, "capacity":{ "name": "容量", "order": 2 }, "pd_type": { "name": "类别", "order": 2 } }, "rules": { "slot": { "type": "Str", "lens": 64, "unique": true }, "model": { "type": "Str", "lens": 64 }, "capacity":{ "type": "Str", "lens": 64 }, "pd_type": { "type": "Str", "lens": 64 } } }
{ "remark": "", "table_classify": 5, "fields": { "slot": { "name": "槽位", "guid": true, "order": 0 }, "manufacturer": { "name": "制造商", "order": 1 }, "model":{ "name": "型号", "order": 2 }, "capacity": { "name": "容量", "order": 3 }, "sn":{ "name": "SN号", "order": 4 }, "speed": { "name": "速率", "order": 5 } }, "rules": { "slot": { "type": "Str", "lens": 64, "unique": true }, "manufacturer": { "type": "Str", "lens": 64 }, "model":{ "type": "Str", "lens": 64 }, "capacity": { "type": "Str", "lens": 64 }, "sn": { "type": "Str", "lens": 64 }, "speed": { "type": "Str", "lens": 64 } } }
{ "remark": "", "table_classify": 7, "fields": { "name": { "name": "标签名", "guid": true, "order": 0 } }, "rules": { "name": { "type": "Str", "lens": 64, "unique": true } } }
- 数据返回格式
1 { 2 "code": 0, 3 "data": { 4 "id": 5, 5 "fields": { 6 "name": { 7 "name": "标签名", 8 "guid": true, 9 "order": 0 10 } 11 }, 12 "create_time": "2021-05-24 22:10:51", 13 "update_time": "2021-05-24 22:10:51", 14 "remark": "", 15 "is_deleted": false, 16 "rules": { 17 "name": { 18 "type": "Str", 19 "lens": 64, 20 "unique": true 21 } 22 }, 23 "table_classify": 7, 24 "parent_table_classify": "通用类" 25 }, 26 "message": null 27 }
- 试图代码
1 def create(self, request, *args, **kwargs): 2 check_field(request.data) 3 table_classify_obj = OperateInstance.get_table_classify(request.data['table_classify']) 4 5 # 判断 table_classify实例是否存在并且不是主分类 6 if not table_classify_obj or not table_classify_obj.pid: 7 return json_error_response('table_classify实例不存在或者table_classify实例为主分类,主分类不允许创建字段表.') 8 return super(TableFieldViewSet, self).create(request, *args, **kwargs)
修改数据
- 验证逻辑
- 如果已经有数据不允许更换分类表.
- 更换分配表判断分类表是否为主分类.
- 其他验证规则同创建保持一致
- URL
-
http://127.0.0.1:8000/api/v1/cmdb/table-field/ID/
-
- 试图代码
def update(self, request, *args, **kwargs): instance = self.get_object() data = request.data # 判断如果更换 table_classify_id 当前 instance 是否存在资产 if instance.table_classify.id != data['table_classify'] and OperateInstance.get_all_asset( instance.table_classify.id): return json_error_response('分类表已经存在资产, 字段表不允许更换主类.') # 判断更换的 table_classify 是否是 主分类表 if not OperateInstance.get_table_classify(data['table_classify']).pid: return json_error_response('指定的分类表为主分类,主分类无法设置表字段.') # 检查数据 check_field(data) return super(TableFieldViewSet, self).update(self, request, *args, **kwargs)
查看数据
- 验证逻辑
- 无
- URL
-
http://127.0.0.1:8000/api/v1/cmdb/table-field/ | http://127.0.0.1:8000/api/v1/cmdb/table-field/ID/
-
- 上传数据格式
- 数据返回格式
- 试图代码
删除数据
- 验证逻辑
- 无
- URL
-
http://127.0.0.1:8000/api/v1/cmdb/table-field/ | http://127.0.0.1:8000/api/v1/cmdb/table-field/ID/
-
- 上传数据格式
- 数据返回格式
- 试图代码
TableData
这个表主要是用于分类表数据的存储.
新增数据
- 验证逻辑
- 根据分类表字段规则进行校验数据, check_data
- URL
-
http://127.0.0.1:8000/api/v1/cmdb/table-data/
-
- 上传数据格式
1 { 2 "remark": "", 3 "table_classify": 2, 4 "data":{ 5 "hostname": "ops107.devops.cc", 6 "manage_ip": "172.16.0.107", 7 "os_platform":"Linux", 8 "os_version": "Centos 7.9.2004", 9 "device_status": "", 10 "cpu_count": "64", 11 "cpu_physical_count": 24, 12 "cpu_model":"志强 E52699 V4", 13 "board_sn": "00:34:87:ce:2f", 14 "board_manufacturer": "英特尔", 15 "board_model": "C610" 16 } 17 }
- 数据返回格式
{ "code": 0, "data": { "id": 7, "create_time": "2021-05-25 13:52:18", "update_time": "2021-05-25 13:52:18", "remark": "", "is_deleted": false, "data": { "hostname": "ops107.devops.cc", "manage_ip": "172.16.0.107", "os_platform": "Linux", "os_version": "Centos 7.9.2004", "device_status": 0, "cpu_count": 64, "cpu_physical_count": 24, "cpu_model": "志强 E52699 V4", "board_sn": "00:34:87:ce:2f", "board_manufacturer": "英特尔", "board_model": "C610" }, "table_classify": 2, "parent_table_classify": "服务器", "field": { "board_sn": { "name": "主板SN号", "order": 5 }, "hostname": { "guid": true, "name": "主机名", "order": 0 }, "cpu_count": { "name": "逻辑CPU", "order": 5 }, "cpu_model": { "name": "cpu_型号", "order": 10 }, "manage_ip": { "name": "管理IP", "order": 1 }, "os_version": { "name": "系统版本", "order": 3 }, "board_model": { "name": "型号", "order": 7 }, "os_platform": { "name": "操作系统", "order": 2 }, "device_status": { "name": "设备状态", "order": 4 }, "board_manufacturer": { "name": "制造商", "order": 6 }, "cpu_physical_count": { "name": "物理CPU", "order": 6 } }, "children": {} }, "message": null }
- 试图代码
1 def create(self, request, *args, **kwargs): 2 3 # 校验数据 4 try: 5 data = check_data(request.data, 'create') 6 except ValueError as e: 7 return json_error_response(f'数据校验出错: {str(e)}') 8 9 serializer = self.get_serializer(data=data) 10 serializer.is_valid(raise_exception=True) 11 self.perform_create(serializer) 12 self.get_success_headers(serializer.data) 13 return json_ok_response(serializer.data)
修改数据
- 验证逻辑
- 数据创建后不可修改分类表
- URL
-
http://127.0.0.1:8000/api/v1/cmdb/table-data/10/
-
- 上传数据格式
{ "remark": "", "data": { "board_sn": "00:34:87:ce:2f", "hostname": "ops11.devops.cc", "cpu_count": 64, "cpu_model": "志强 E52699 V4", "manage_ip": "172.16.0.11", "os_version": "Centos 7.9.2004", "board_model": "C610", "os_platform": "Linux", "device_status": 0, "board_manufacturer": "英特尔", "cpu_physical_count": 24 }, "table_classify": 2 }
- 数据返回格式
{ "code": 0, "data": { "id": 10, "create_time": "2021-05-25 13:55:00", "update_time": "2021-05-25 21:01:24", "remark": "", "is_deleted": false, "data": { "board_sn": "00:34:87:ce:2f", "hostname": "ops11.devops.cc", "cpu_count": 64, "cpu_model": "志强 E52699 V4", "manage_ip": "172.16.0.11", "os_version": "Centos 7.9.2004", "board_model": "C610", "os_platform": "Linux", "device_status": 0, "board_manufacturer": "英特尔", "cpu_physical_count": 24 }, "table_classify": 2 }, "message": null }
- 试图代码
def update(self, request, *args, **kwargs): instance = self.get_object() try: data = check_data(request.data, instance) except ValueError as e: return json_error_response(f'数据校验出错: {str(e)}') if data.get('table_classify') and data.get( 'table_classify') != instance.table_classify.id: return json_error_response('数据不可修改类型, 如需更换请进行删除.') partial = kwargs.pop('partial', False) serializer = self.get_serializer(instance, data=data, partial=partial) serializer.is_valid(raise_exception=True) self.perform_update(serializer) if getattr(instance, '_prefetched_objects_cache', None): instance._prefetched_objects_cache = {} return json_ok_response(serializer.data)
数据绑定
- 验证逻辑
- 验证有没有分类关系表 为 parent_table_id 和 child_table_id
- 判断分类表有没有响应的资产数据, 即查询条件 table_classify_id = parent_table_id & id = parent_asset_id
- 如果 关系绑定实例的 is_foreign_key == False, 需要判断子资产有没有被其他资产绑定过.
- URL
-
http://127.0.0.1:8000/api/v1/cmdb/table-field/ | http://127.0.0.1:8000/api/v1/cmdb/table-field/ID/
-
- 上传数据格式
{ "parent_table_id": 2, "child_table_id": 3, "parent_asset_id": 2, "child_asset_id": 8 }
- 数据返回格式
{ "code": 0, "data": "资产数据绑定成功", "message": null }
- 试图代码
1 @action(methods=['post'], detail=False) 2 def relation(self, request, *args, **kwargs): 3 data = request.data 4 5 parent_table_id = data['parent_table_id'] 6 child_table_id = data['child_table_id'] 7 table_relation_obj = OperateInstance.get_table_relation(parent_table_id, child_table_id) 8 # 判断分类关系绑定表是否存在 9 if not table_relation_obj: 10 return json_error_response('未查询到分类关系绑定表, 请先进行绑定在进行资产绑定操作.') 11 12 parent_asset_obj = OperateInstance.get_classify_asset(data['parent_asset_id'], parent_table_id) 13 child_asset_obj = OperateInstance.get_classify_asset(data['child_asset_id'], child_table_id) 14 15 # 判断资产是否存在 16 if not parent_asset_obj or not child_asset_obj: 17 return json_error_response('资产数据未查询到.') 18 19 # 判断是否为 OneToOne 如果是则判断是否存在绑定记录 20 if not table_relation_obj.is_foreign_key: 21 print('1111111111111') 22 asset_relation_obj = OperateInstance.get_child_asset_relation(table_relation_obj.id, data['child_asset_id']) 23 24 if asset_relation_obj: 25 return json_error_response('类型表关联模式为: OneToOne, 子资产数据已经被绑定无法进行二次绑定.') 26 27 try: 28 new_asset_relation = AssetsRelation.objects.create(parent_asset=parent_asset_obj, 29 child_asset=child_asset_obj, 30 table_relation=table_relation_obj) 31 new_asset_relation.save() 32 except Exception as e: 33 return json_error_response(f'数据创建出错: {str(e)}') 34 return json_ok_response('资产数据绑定成功')
数据解绑
- 验证逻辑
- 无
- URL
-
http://127.0.0.1:8000/api/v1/cmdb/table-field/ | http://127.0.0.1:8000/api/v1/cmdb/table-field/ID/
-
- 上传数据格式
- 数据返回格式
- 试图代码
数据删除
- 验证逻辑
- 无
- URL
-
http://127.0.0.1:8000/api/v1/cmdb/table-field/ | http://127.0.0.1:8000/api/v1/cmdb/table-field/ID/
-
- 上传数据格式
- 数据返回格式
- 试图代码
数据查看
- 验证逻辑
- 无
- URL
-
http://127.0.0.1:8000/api/v1/cmdb/table-field/ | http://127.0.0.1:8000/api/v1/cmdb/table-field/ID/
-
- 上传数据格式
- 数据返回格式
- 试图代码
http://127.0.0.1:8000/api/v1/cmdb/table-field/1/
作者:闫世成
出处:http://cnblogs.com/yanshicheng
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。如有问题或建议,请联系上述邮箱,非常感谢。