Django批量插入Asset数据时如何通过AssetType名称替换外键ID
解决方案
你遇到的报错本质是Asset数据库表不存在asset_type_name字段,外键关联存储的是asset_type_id,直接插入字段不匹配才会失败。最简单的转换方法是先查询AssetType的名称与ID映射关系,在DataFrame层面完成字段转换后再执行插入操作。
修改后的视图代码如下:
from rest_framework import status from rest_framework.response import Response class AssetViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): """ A simple ViewSet for viewing and editing accounts. """ queryset = Asset.objects.select_related() serializer_class = AssetSerializer @action(methods=['POST'], detail=False) def bulk_create(self, request): df = pd.DataFrame.from_dict(dict(request.data['data'])) # 1. 一次性查询所有资产类型的name到id的映射(因name字段唯一,无需担心重复) asset_type_mapping = dict(AssetType.objects.values_list('name', 'id')) # 2. 转换名称为对应的ID,生成外键字段 df['asset_type_id'] = df['asset_type_name'].map(asset_type_mapping) # 可选:校验是否有不存在的资产类型,提前拦截异常 invalid_type_names = df[df['asset_type_id'].isna()]['asset_type_name'].unique() if len(invalid_type_names) > 0: return Response( {"error": f"以下资产类型未预先定义:{', '.join(invalid_type_names)}"}, status=status.HTTP_400_BAD_REQUEST ) # 3. 删除不需要的名称字段,仅保留表结构存在的字段 df = df.drop(columns=['asset_type_name']) # 4. 执行批量插入 df.to_sql( Asset._meta.db_table, con=engine, if_exists='append', index=False, chunksize=500 ) return Response({"message": "批量插入成功"}, status=status.HTTP_201_CREATED)
补充说明
这个方案效率很高,AssetType全表查询只会执行1次,不需要逐行查库,适配SQL Server数据库,也适合批量大数据场景。
如果你的数据量不大,想通过Django序列化器自动完成转换,可以修改AssetSerializer的字段定义实现:
class AssetSerializer(serializers.ModelSerializer): # 改为SlugRelatedField,指定通过name字段关联AssetType,支持自动读写转换 asset_type = serializers.SlugRelatedField( slug_field='name', queryset=AssetType.objects.all() ) class Meta: model = Asset fields = ("id", "asset_type", "asset_name", "display_name")
修改后直接调用序列化器批量校验+bulk_create即可完成插入,不需要手动处理DataFrame字段映射。
内容的提问来源于stack exchange,提问作者Shubham Periwal
相关产品推荐
相关产品推荐

