Django - повторение элементов словаря и сохранение их порождает проблемы на уровне соединений с базой данных? - PullRequest
1 голос
/ 09 мая 2019

Я работаю с приложением для опроса, поэтому мне нужно сохранить все ответы пользователя в базе данных.Я делаю это так:

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 раз, или жесделать это только один раз?

  2. Есть ли лучший способ сохранить информацию POST вручную?(без использования форм django, так как по разным причинам мне нужно сделать это вручную)

1 Ответ

2 голосов
/ 09 мая 2019

Это определенно не хороший способ хранения Answer с навалом, так как:

  1. вы каждый раз выбираете объект Item для каждого вопроса;
  2. ваш код не правильно обрабатывает случай, когда элемент отсутствует: в этом случае он вызовет исключение, а промежуточное программное обеспечение Django (вероятно) отобразит 500 страниц; и
  3. будет сделано несколько вызовов для создания всех этих объектов.

Мы можем создавать объекты в больших объемах, чтобы уменьшить количество запросов. Как правило, мы создаем все элементы с помощью одного запроса, хотя в зависимости от базы данных и объема данных может потребоваться ограниченное количество запросов.

Более того, нам не нужно извлекать связанные Item объекты, на всех , мы можем просто установить поле item_id вместо "двойника" item ForeignKey поле, например:

из django.db import IntegrityError

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

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

bulk_create, таким образом, вставит все объекты в небольшое количество запросов и, таким образом, значительно сократит время запроса.

Обратите внимание, что bulk_create имеет некоторые ограничения (перечисленные на странице документации). Может быть полезно прочитать их внимательно и принять их во внимание. Хотя я думаю, что в данном случае они не актуальны, всегда лучше знать ограничения инструментов, которые вы используете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...