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

Django执行bulk_create批量创建前如何在定义对象阶段判定重复数据

实现重复数据校验的方案

你原本设想的if data['title'] in videos:逻辑无法直接生效,因为videos列表里存储的是Video类实例,不是标题字符串,我们可以通过额外维护一个已处理标题的集合,实现你要的判断效果。


方案1:仅校验本次导入批次内的重复数据

修改后代码如下:

videos = []
throughs = []
# 新增:存储已处理过的标题,用于去重
processed_titles = set()
# 新增:暂存每个视频对应的标签主键,批量创建完视频后再处理关联表
video_tag_map = []

for datas in files:
    for data in datas:
        # 完全符合你预期的判断逻辑,重复则直接跳过当前数据
        if data["title"] in processed_titles:
            continue
        # 标题不重复则加入已处理集合
        processed_titles.add(data["title"])
        
        tags = data["tags"].split()
        tag_pks = list(
            set([Tag.objects.get_or_create(name=tag)[0].pk for tag in tags])
        )

        video = Video(
            title=data["title"],
            thumbnail_url=data["thumbnail_url"],
            preview_url=data["preview_url"],
            embed_url=data["embed_url"],
            embed_source=data["embed_source"],
            duration=data["duration"],
            published_at=data["published_at"],
        )
        videos.append(video)
        # 暂存当前视频对应的标签主键
        video_tag_map.append(tag_pks)

# 批量创建视频,创建后video实例会自动填充主键(PostgreSQL、MySQL 5.7+等主流数据库均支持自动返回主键)
Video.objects.bulk_create(videos)

# 遍历创建好的视频和对应的标签,生成关联表数据
for video, tag_pks in zip(videos, video_tag_map):
    for tag_pk in tag_pks:
        throughs.append(
            Video.tags.through(video_id=video.pk, tag_id=tag_pk)
        )
Video.tags.through.objects.bulk_create(throughs)

方案2:同时校验数据库中已存在的重复数据

如果需要避免导入数据库中已经存储过的视频,只需要修改processed_titles的初始化逻辑,提前把数据库中已有的标题查出来即可:

# 初始化时直接加载数据库中所有已存视频标题
processed_titles = set(Video.objects.values_list("title", flat=True))

其余逻辑和方案1完全一致。


额外说明

原有代码中在创建Video实例后、bulk_create执行前就取video.pk的逻辑存在问题:未入库的实例没有主键值,会导致关联表数据插入失败,上面的代码已经调整了执行顺序,先批量创建视频拿到主键后再处理关联表。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 17:45:08