You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django读取CSV文件用bulk_create创建对象时如何建立多对多关联

你的实现思路整体正确,通过bulk_create批量创建GS实例减少数据库IO的优化方向是对的,只需要补充多对多中间表的批量插入逻辑即可完成需求,具体实现如下:

实现步骤
  1. 遍历CSV行时,同时存储GS实例和对应关联的语言编码列表,方便后续匹配
  2. 利用Django bulk_create 自动填充主键的特性(PostgreSQL、MySQL 5.7+等主流数据库均支持),直接获取批量创建后的GS实例ID
  3. 提前将所有用到的Lang对象转为编码到ID的映射字典,避免重复查询数据库
  4. 获取多对多字段自动生成的中间表模型,批量插入关联数据
完整修改后代码
def handle(self, *args, **options):
    path = 'path/to/file.csv'
    df = pd.read_csv(path)
    # 存储(GS实例, 关联语言编码列表)的配对关系
    gs_lang_pairs = []
    all_lang_codes = set()

    for i, row in df.iterrows():
        # 处理语言编码
        lang_codes = [c.strip() for c in row['Lang'].split(';')]
        all_lang_codes.update(lang_codes)
        # 创建GS实例暂存
        segment = GS(name=row['Name'])
        gs_lang_pairs.append((segment, lang_codes))
    
    # 批量创建GS实例,执行后实例会自动填充id主键
    GS.objects.bulk_create([pair[0] for pair in gs_lang_pairs])

    # 一次性查询所有用到的Lang对象,构建编码到ID的映射
    lang_map = {lang.code: lang.id for lang in Lang.objects.filter(code__in=all_lang_codes)}

    # 获取多对多中间表模型
    GSLangThrough = GS.country_code.through
    # 组装所有中间表记录
    through_records = []
    for gs, lang_codes in gs_lang_pairs:
        for code in lang_codes:
            lang_id = lang_map.get(code)
            if lang_id: # 过滤不存在的编码避免报错
                through_records.append(GSLangThrough(gs_id=gs.id, lang_id=lang_id))
    
    # 批量插入关联关系
    GSLangThrough.objects.bulk_create(through_records)
注意事项
  • 如果使用的数据库不支持bulk_create返回主键,可在批量创建GS后,通过GS.objects.filter(name__in=[pair[0].name for pair in gs_lang_pairs])查询所有已创建的实例,再和原始行配对即可,需保证GS的name字段唯一
  • 该方案全程仅执行3次数据库写入/查询操作,性能远高于逐行创建实例、逐行添加关联的实现方式

内容的提问来源于stack exchange,提问作者Jekson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 18:06:03