Django中表单提交数据高效保存与更新的实现方案
方案优化思路与实现
核心调整前提
由于原有提交逻辑仅上传文本内容,无法区分内容对应的数据库记录,首先需要前端配合做小调整:
- 渲染预填充表单时,为每个已存在的
Sentence记录对应的输入框绑定原数据库主键id - 提交时每条内容需附带对应的id值,新增的内容id统一传
0或空字符串做标识
可以选择两种提交方式:两个索引一一对应的列表sentence_ids、sentence_contents,或者直接传结构化JSON列表,每个元素包含id和content字段。
后端优化逻辑
核心是避免全量删改,仅做增量操作,同时用Django批量操作接口减少数据库交互次数:
- 先拉取当前用户所有存量数据,用id做索引存入字典,降低查询开销
- 对比提交数据和存量数据,拆分出「待删除」「待更新」「待新增」三类数据
- 分别对三类数据做批量操作,无变更时直接跳过所有数据库操作
- 增加事务保证操作原子性,避免中途出错导致数据异常
优化后代码实现
from .models import Sentence from django.db import transaction def index(request): if request.method == "POST" and request.user.is_authenticated: # 前端提交两个对应索引的列表:id列表和内容列表 sentence_ids = request.POST.getlist("sentence_id") sentence_contents = request.POST.getlist("sentence_content") # 开启事务保证所有操作原子性 with transaction.atomic(): # 1. 拉取当前用户所有存量数据,构建id到记录的映射 existing_sentences = Sentence.objects.filter(user=request.user).in_bulk() existing_ids = set(existing_sentences.keys()) submitted_valid_ids = set() to_update = [] to_create = [] # 2. 遍历提交数据拆分待更新、待新增记录 for sid, content in zip(sentence_ids, sentence_contents): # 可根据业务需求决定是否过滤空内容 if not content.strip(): continue try: record_id = int(sid) except (ValueError, TypeError): record_id = 0 if record_id > 0 and record_id in existing_ids: # 已有记录,对比内容判断是否需要更新 submitted_valid_ids.add(record_id) if existing_sentences[record_id].sentence != content: existing_sentences[record_id].sentence = content to_update.append(existing_sentences[record_id]) else: # 新增记录暂存 to_create.append(Sentence(user=request.user, sentence=content)) # 3. 批量删除:存量id不在提交的有效id范围内的记录 to_delete_ids = existing_ids - submitted_valid_ids if to_delete_ids: Sentence.objects.filter(id__in=to_delete_ids).delete() # 4. 批量更新内容有变更的记录 if to_update: Sentence.objects.bulk_update(to_update, ['sentence']) # 5. 批量新增记录 if to_create: Sentence.objects.bulk_create(to_create) # 其他原有代码
优化效果说明
完全适配四种提交场景,性能提升明显:
- 用户仅编辑部分已有字段:仅批量更新变更的记录,无额外开销
- 用户新增部分字段:仅批量插入新增记录
- 用户删除部分已有字段:仅批量删除被移除的记录
- 用户未做任何修改:所有数据库操作全部跳过,零开销
原有实现需要N+1次数据库交互(1次全量删除+N次单条插入),优化后最多只有3次数据库操作,数据量越大性能优势越显著。
内容的提问来源于stack exchange,提问作者Vaibhav
相关产品推荐
相关产品推荐

