Django REST Framework POST请求外键关联与多错误处理问题
问题1解决方案
报错的核心原因是你把序列化器对象和模型实例搞混了:deviceserializer是序列化器类的对象,不是你创建的Device模型实例,它本身没有id属性,也不能直接赋值给外键字段DD2DKEY。
调用序列化器的save()方法会返回已经写入数据库的模型实例,直接拿这个实例赋值给外键即可,对应代码修改如下:
# 原代码 if deviceserializer.is_valid() and devdserializer.is_valid(): deviceserializer.save() devdserializer.save(DD2DKEY=deviceserializer.id) # 修改后代码 if deviceserializer.is_valid() and devdserializer.is_valid(): # 接收save返回的已创建Device实例 device_obj = deviceserializer.save() # 直接把实例传给外键字段 devdserializer.save(DD2DKEY=device_obj)
额外提醒:你DeviceDetail模型的__str__方法里返回self.hostname是错误的,DeviceDetail没有hostname字段,后续调用会报错,可以改成return self.DD2DKEY.hostname。
问题2解决方案
报错是因为Python中and运算符的短路逻辑:如果前面的deviceserializer.is_valid()返回False,后面的devdserializer.is_valid()会直接跳过不执行。当你进入else分支访问devdserializer.errors时,这个序列化器根本没有调用过is_valid(),就会触发这个断言错误。
修改方法是提前单独调用两个序列化器的is_valid(),避免短路:
@api_view(['POST']) def create_device(request): deviceserializer = DeviceSerializers(data = request.data) devdserializer = DeviceDetailSerializers(data = request.data) # 单独调用两个is_valid,确保都执行过 device_valid = deviceserializer.is_valid() detail_valid = devdserializer.is_valid() if device_valid and detail_valid: device_obj = deviceserializer.save() devdserializer.save(DD2DKEY=device_obj) results = { "device":deviceserializer.data, "device_details" : devdserializer.data, } return Response(results, status=status.HTTP_201_CREATED) else: errors = { "device":deviceserializer.errors, "device_details" : devdserializer.errors, } return Response(errors, status=status.HTTP_400_BAD_REQUEST)
另外补充:你初始化序列化器的时候如果是创建新数据,不需要提前实例化空的模型对象,直接传data参数即可,上面的修改代码里已经把多余的空实例初始化去掉了。
内容的提问来源于stack exchange,提问作者L.Calvin
相关产品推荐
相关产品推荐

