Есть ли более эффективный способ для этого?
for item in item_list:
e, new = Entry.objects.get_or_create(
field1 = item.field1,
field2 = item.field2,
)
Есть ли более эффективный способ для этого?
for item in item_list:
e, new = Entry.objects.get_or_create(
field1 = item.field1,
field2 = item.field2,
)
Вы не можете делать приличные массовые вставки с помощью get_or_create (или даже создавать), и нет API для этого легко.
Если ваша таблица достаточно проста, что создание строк с необработанным SQL не слишком больно, это не слишком сложно; что-то вроде:
INSERT INTO site_entry (field1, field2)
(
SELECT i.field1, i.field2
FROM (VALUES %s) AS i(field1, field2)
LEFT JOIN site_entry as existing
ON (existing.field1 = i.field1 AND existing.field2 = i.field2)
WHERE existing.id IS NULL
)
где% s - строка, подобная ("field1, field2"), ("field3, field4"), ("field5, field6")
, которую вы должны будете создать и убежать должным образом самостоятельно.
В зависимости от того, на что вы нацеливаетесь. Вы можете использовать функцию manage.py
loaddata
для загрузки данных в соответствующем формате (JSON, XML, YAML,...).
См. также это обсуждение.
Если вы не уверены, что вещи в вашем item_list
уже существуют в вашей базе данных, и вам нужны объекты модели, тогда get_or_create
- это определенно путь.
Если вы знаете, что элементы НЕ в вашей БД, вы бы гораздо лучше сделали:
for item in item_list:
new = Entry.objects.create(
field1 = item.field1,
field2 = item.field2,
)
И если вам не нужны объекты, просто игнорируйте возврат из вызова функции. Это не ускорит работу базы данных DB, но это поможет в управлении памятью, если это проблема.
Если вы не уверены, что данные уже находятся в БД, но в этом поле есть флаг unique=True
, тогда БД будет обеспечивать уникальность, и вы можете просто поймать исключение и перейти дальше. Это предотвратит добавление дополнительного БД, избегая попытки выбрать существующий объект.
from django.db import IntegrityError
for item in item_list:
try:
new = Entry.objects.create(
field1 = item.field1,
field2 = item.field2,
)
except IntegrityError:
continue
Вы можете увеличить скорость в любом случае, вручную управляя транзакциями. Django автоматически создаст и совершит транзакцию для каждого сохранения, но предоставит некоторые декораторы, которые значительно повысят эффективность, если вы знаете, что вы будете делать много резервных копий БД в определенной функции. В документах Django лучше объяснить все это, чем здесь, но вы, вероятно, захотите обратить особое внимание на django.db.transaction. commit_on_success
Начиная с 1.4 вы можете делать bulk_create
Смотрите документы
* Обратите внимание на предостережения, хотя (самое главное, что метод save() не будет вызываться, и поэтому сигналы pre_save и post_save не будут отправлены.) *
Я бы сказал, что нет.
Но мне интересно, какой тип ваш item
, если они имеют атрибуты field1
и field2
. Похоже, существует другой класс, представляющий запись, но не получен из models.Model
. Возможно, вы можете опустить этот класс и сразу создать экземпляры Entry
вместо создания этих элементов.