Django导入CSV创建关联模型时触发TransactionManagementError怎么解决
错误根因
- 你的代码运行在一个外层
atomic事务块中,在执行POL的get_or_create之前,前面的逻辑(比如PO创建时的信号触发、关联product的查询逻辑、PO的JSONField字段约束校验)已经触发了未捕获的数据库异常,Django会将当前事务标记为需要回滚,此时任何后续的数据库操作都会抛出TransactionManagementError。 - 额外的冗余操作也可能放大问题:你通过
po.purchaseorderline_set调用get_or_create时,重复传入了purchase_order=po筛选参数,同时get_or_create返回的实例已经持久化到数据库,你额外调用的pol.save()属于冗余操作,若POL模型有自定义逻辑可能重复触发异常。
修复步骤
- 第一步:给每行的处理逻辑增加独立事务和异常捕获,定位具体报错点,同时避免单条数据异常导致整个导入任务失败,修改后的参考代码如下:
@classmethod def parse_purchase_order_from_csv(cls, purchase_file, store_id, supplier_id=0, field_mapping='', invoice_number='', create_product=False, scrape=False): import pandas as pd from django.db import transaction # 原有CSV解析逻辑保留 df = df.dropna(how='all') lines = len(df) for row in df.itertuples(): status = { 'total_lines': lines, 'lines_processed': 1, 'lines_success': 0, 'error_lines': [] } # 原有单行数据字段解析逻辑保留 try: # 单条数据用独立事务包裹,异常只回滚单条数据的操作 with transaction.atomic(): po, po_created = cls.objects.get_or_create( internal_id=internal_id, supplier=supplier, store_id=store_id, defaults={ 'purchase_date': purchase_date, 'status': status } ) if po.completed: continue # 原有关联product的逻辑保留 # 去掉冗余的purchase_order参数和多余的save调用 if product: pol, pol_created = po.purchaseorderline_set.get_or_create( label=label, ean=row[ean_col + 1], defaults={ 'amount': row[quantity_col + 1], 'label': label, 'product': product, 'ean': row[ean_col + 1], } ) else: pol, pol_created = po.purchaseorderline_set.get_or_create( label=label, ean=row[ean_col + 1], defaults={ 'amount': row[quantity_col + 1], 'label': label, 'ean': row[ean_col + 1], } ) po.status['lines_success'] += 1 po.save() except Exception as e: # 打印具体异常即可定位真正的报错点(比如PO信号异常、product查询异常、字段约束不满足) print(f"第{row.Index}行处理失败,错误:{str(e)}") # 按需补充错误行记录逻辑 continue
- 第二步:排查PO、POL模型的自定义
save方法、pre_save/post_save等信号逻辑,确认没有隐藏的未捕获异常。 - 第三步:确认PO的
status字段的JSON格式符合数据库约束,比如PostgreSQL的JSONField不允许存储不可序列化的Python对象。
内容的提问来源于stack exchange,提问作者Patrick Gerrits
相关产品推荐
相关产品推荐

