Django遍历字典存储数据的数据库连接问题及优化咨询
嘿,我来帮你解答这两个问题,顺便给你优化下代码~
第一个问题:数据库连接会打开关闭60次吗?
完全不会!Django的数据库连接是绑定在请求生命周期里的:当你的视图第一次执行数据库操作(比如第一个Item.objects.get())时,Django会建立一个数据库连接,之后整个请求处理过程中所有的ORM操作都会复用这个连接,直到请求处理完成、响应返回给用户之后,Django才会关闭这个连接。
所以哪怕你循环60次执行ORM操作,全程也只会用同一个数据库连接,不用担心里面有60次开开关关的开销。
第二个问题:更高效的手动保存方式
你现在的写法每次循环都调用Answer.objects.create(),这会给数据库发60条INSERT语句,数据量大的时候效率很低。推荐用Django ORM提供的bulk_create()方法,一次性批量插入所有数据,只需要1次(或极少数几次)数据库交互。
另外还要提个小bug:你原来代码里的if item == None是无效的——因为Item.objects.get()如果找不到对应主键的记录,会直接抛出Item.DoesNotExist异常,不会返回None,所以这个判断永远不会触发,反而会让程序直接报错。应该用try-except来捕获异常。
优化后的代码大概是这样:
answers = [] for key, value in request.POST.items(): # 跳过csrf token if key == 'csrfmiddlewaretoken': continue try: item = Item.objects.get(pk=key) except Item.DoesNotExist: # 找不到对应问题时返回错误页 return render(request, "survey/error.html") # 先把Answer实例加到列表里,不急着保存 answers.append(Answer(item=item, answer=value, user=request.user)) # 一次性批量插入所有记录 Answer.objects.bulk_create(answers)
关于bulk_create的注意事项:
- 它不会触发模型的
save()方法,也不会发送post_save/pre_save信号,如果你的业务依赖这些信号,可能需要额外处理; - 如果你的Answer模型有唯一约束(比如同一个用户不能重复回答同一个问题),要确保批量插入的列表里没有重复数据,否则会抛出数据库异常;
- 不同数据库对bulk_create的支持略有差异,但大部分主流数据库(MySQL、PostgreSQL、SQLite)都能很好适配。
内容的提问来源于stack exchange,提问作者ozo
相关产品推荐
相关产品推荐

