无法向Django的Hostinfo模型插入数据,请求排查view.py问题
Django Hostinfo模型无法插入数据的问题排查与修复
提交的JSON数据
{"rawdata": [{"id": "89729999","name": "testname","product": "testproduct","modified_at": "2023-12-14T03:00:00.000Z","modified_by": "personname","asset": {"configname": ["testconfig"],"serialnumber": ["testserialnumber"],"owner": ["owner1","owner2"]}}]}
模型定义(models.py)
class Host(models.Model): id = models.CharField(primary_key=True, max_length=15) name = models.CharField(max_length=80) product = models.CharField(max_length=50) modified_at = models.DateTimeField() modified_by = models.CharField(max_length=50) class Hostinfo(models.Model): fk = models.ForeignKey(Host, on_delete=models.CASCADE) ## id parameter_section = models.CharField(max_length=40) parameter = models.CharField(max_length=80) parameter_index = models.IntegerField() ## index value = models.CharField(max_length=200, null=True) modified_at = models.DateTimeField() modified_by = models.CharField(max_length=50)
现有视图代码(views.py)
@api_view(('POST',)) def hostrequest(request): data=request.data.get('rawdata') print(data) try: for item in data: host=Host() host.cmdbid = item['id'] host.name = item['name'] host.product =item['product'] host.modified_at= item['modified_at'] host.modified_by= item['modified_by'] host.save() hostparameter = Hostinfo() for parameter_section in item: if parameter_section != "id" and parameter_section != "name" and parameter_section != "product" and parameter_section != "modified_at" and parameter_section != "modified_by": detailData = item[parameter_section] for parameter in detailData: parameters = detailData[parameter] for parameter_index in parameters: value = parameters[parameter_index] hostparameter.fk += item['id'] hostparameter.parameter_section += parameter_section['parameter_section'] hostparameter.parameter += parameter['parameter'] hostparameter.parameter_index += parameter_index['parameter_index'] hostparameter.value += value['value'] hostparameter.save() response_data={"error":False,"Message":"Updated Successfully"} return JsonResponse(response_data,safe=False,status=status.HTTP_201_CREATED) except: response_data={"error":True,"Message":"Failed to Update Data"} return JsonResponse(response_data,safe=False)
问题现象
执行视图后无报错提示,Host模型数据插入成功,但Hostinfo模型无数据写入,期望的Hostinfo数据如下:
| fk | parameter_section | parameter | parameter_index | value | modified_at |
|---|---|---|---|---|---|
| 89729999 | asset | configname | 0 | testconfig | 2023-12-14T03:00:00.000Z |
| 89729999 | asset | owner | 0 | owner1 | 2023-12-14T03:00:00.000Z |
| 89729999 | asset | owner | 1 | owner2 | 2023-12-14T03:00:00.000Z |
问题分析
现有视图代码存在多处逻辑错误,导致Hostinfo无法正常插入数据:
- Host字段赋值错误:Host模型主键为
id,但视图中使用host.cmdbid = item['id'],该字段不存在,虽你反馈Host数据插入成功,大概率是笔误,实际应改为host.id = item['id']。 - Hostinfo实例初始化位置错误:仅在循环外创建一次
Hostinfo对象,后续修改会覆盖已有数据且无法生成新记录,需为每条待插入数据新建实例。 - 循环遍历逻辑错误:
- 遍历参数列表时直接取元素而非索引,导致
parameter_index拿到的是值而非索引,后续parameters[parameter_index]会触发索引错误。 - 错误将字符串类型的
parameter_section、parameter当作字典访问(如parameter_section['parameter_section']),会抛出异常被全局except捕获,直接返回失败响应。
- 遍历参数列表时直接取元素而非索引,导致
- 外键赋值错误:Hostinfo的
fk是ForeignKey字段,需赋值为已保存的Host实例,而非字符串ID,且不能使用+=操作。 - 必填字段缺失:Hostinfo的
modified_at和modified_by字段未赋值,插入时会触发数据库约束错误。 - 全局异常捕获隐藏问题:
except:捕获所有异常,导致无法看到具体错误信息,阻碍排查。
修复后的视图代码
from django.http import JsonResponse from rest_framework.decorators import api_view from rest_framework import status from .models import Host, Hostinfo import traceback @api_view(('POST',)) def hostrequest(request): data = request.data.get('rawdata') if not data: return JsonResponse({"error": True, "Message": "No rawdata provided"}, status=status.HTTP_400_BAD_REQUEST) try: for item in data: # 创建并保存Host实例 host = Host( id=item['id'], name=item['name'], product=item['product'], modified_at=item['modified_at'], modified_by=item['modified_by'] ) host.save() # 处理嵌套的参数部分(如asset) for section_name, section_data in item.items(): # 跳过Host已有的字段 if section_name in ['id', 'name', 'product', 'modified_at', 'modified_by']: continue # 遍历每个参数(如configname、serialnumber) for param_name, param_values in section_data.items(): # 遍历参数的每个值和索引 for idx, value in enumerate(param_values): # 为每个值新建Hostinfo实例 host_info = Hostinfo( fk=host, parameter_section=section_name, parameter=param_name, parameter_index=idx, value=value, modified_at=item['modified_at'], modified_by=item['modified_by'] ) host_info.save() return JsonResponse({"error": False, "Message": "Updated Successfully"}, status=status.HTTP_201_CREATED) except Exception as e: # 打印异常信息用于排查 traceback.print_exc() return JsonResponse({"error": True, "Message": f"Failed to Update Data: {str(e)}"}, status=status.HTTP_400_BAD_REQUEST)
修复说明
- 修正Host字段赋值,通过模型初始化方法创建实例,简洁可靠。
- 将Hostinfo实例创建移至内层循环,确保每条数据对应一个新实例。
- 使用
enumerate遍历参数值,同时获取索引和值,解决索引错误问题。 - 直接将已保存的Host实例赋值给外键
fk,符合Django外键要求。 - 补充Hostinfo的
modified_at和modified_by字段赋值,满足数据库约束。 - 替换全局异常捕获为
Exception as e,打印异常堆栈信息并返回具体错误,方便排查。
内容的提问来源于stack exchange,提问作者Shan
相关产品推荐
相关产品推荐

