Django-迭代字典的元素并保存它们会在与数据库的连接级别上产生问题吗?

时间:2019-05-09 14:57:24

标签: django django-forms

我正在使用调查应用程序,因此我需要将用户给出的所有答案保存在数据库中。我这样做的方式是这样的:

for key, value in request.POST.items(): 
       if key != 'csrfmiddlewaretoken': # I don't want to save the token info
          item = Item.objects.get(pk=key) # I get the question(item) I want to save
          if item == None:
            return render(request, "survey/error.html")
          Answer.objects.create(item= item, answer=value, user = request.user)

考虑到django默认情况下会关闭与数据库的连接(即不使用持久连接)。我的问题是:

  1. 例如,如果词典有60个问题的答案(因此它将重复60次),它将打开和关闭连接60次,还是仅执行一次?

    < / li>
  2. 是否有更好的方法手动保存POST信息? (不使用Django表单,因为出于各种原因,我目前需要手动执行此操作)

1 个答案:

答案 0 :(得分:2)

这绝对不是 批量存储Answer的好方法,因为:

  1. 您每次为每个问题获取Item对象;
  2. 您的代码不能正确地处理缺少项的情况:在这种情况下,它将引发异常,并且Django中间件(可能)将渲染500页;和
  3. 它将进行多次调用以创建所有这些对象。

我们可以批量创建对象以减少查询数量。通常,我们将使用单个查询创建所有元素,尽管取决于数据库和数据量,它可能需要有限数量的查询。

我们进一步不需要完全获取相关的Item对象, ,我们只需设置item_id字段, item ForeignKey字段的“双胞胎”,例如:

从django.db导入IntegrityError

try:
    answers = [
        Answer(item_id=key, answer=value, user=request.user)
        for key, value in request.POST.items()
        if key != 'csrfmiddlewaretoken'
    ]

    Answer.objects.bulk_create(answers)
except IntegrityError:
    return render(request, 'survey/error.html')

bulk_create将在少量查询中插入所有对象,从而大大减少了请求时间。

请注意,bulk_create有一些限制(在文档页面上列出)。仔细阅读这些内容并加以考虑可能会很有用。尽管我认为在给定的情况下这些都不相关,但最好还是了解所使用工具的局限性。