Mam wiele obiektów do zapisania w bazie danych, dlatego chcę z nimi tworzyć instancje modelu.
Dzięki django mogę tworzyć wszystkie instancje modeli MyModel(data)
, a następnie chcę je wszystkie zapisać.
Obecnie mam coś takiego:
for item in items:
object = MyModel(name=item.name)
object.save()
Zastanawiam się czy mogę bezpośrednio zapisać listę obiektów np:
objects = []
for item in items:
objects.append(MyModel(name=item.name))
objects.save_all()
Jak zapisać wszystkie obiekty w jednej transakcji?
django
django-models
Alexis Métaireau
źródło
źródło
Odpowiedzi:
od czasu rozwoju django istnieje
bulk_create
metoda menedżera obiektów, która przyjmuje jako dane wejściowe tablicę obiektów utworzonych przy użyciu konstruktora klasy. sprawdź dokumentację djangoźródło
bulk_create
: docs.djangoproject.com/en/dev/ref/models/querysets/#bulk-createIf the model’s primary key is an AutoField it does not retrieve and set the primary key attribute, as save() does, unless the database backend supports it (currently only PostgreSQL).
bulk_create()
nie wyzwala żadnych sygnałów. Zastanawiam się dlaczego.Użyj
bulk_create()
metody. Jest teraz standardem w Django.Przykład:
Entry.objects.bulk_create([ Entry(headline="Django 1.0 Released"), Entry(headline="Django 1.1 Announced"), Entry(headline="Breaking: Django is awesome") ])
źródło
pracował dla mnie, aby użyć ręcznej obsługi transakcji dla pętli (postgres 9.1):
from django.db import transaction with transaction.commit_on_success(): for item in items: MyModel.objects.create(name=item.name)
w rzeczywistości to nie to samo, co „natywne” wstawianie zbiorcze do bazy danych, ale pozwala uniknąć / zmniejszyć transport / operacje orms / kwerendę sql analizować koszty
źródło
commit_on_success
. Powinieneś użyćtransaction.atomic()
Zobacz: stackoverflow.com/questions/21861207/ ...Oto jak zbiorczo tworzyć encje z pliku rozdzielanego kolumnami, pomijając wszystkie procedury bez cytowania i zmiany znaczenia:
SomeModel(Model): @classmethod def from_file(model, file_obj, headers, delimiter): model.objects.bulk_create([ model(**dict(zip(headers, line.split(delimiter)))) for line in file_obj], batch_size=None)
źródło
w przypadku implementacji jednowierszowej w mapie można użyć wyrażenia lambda
map(lambda x:MyModel.objects.get_or_create(name=x), items)
Tutaj lambda dopasowuje każdą pozycję na liście pozycji do x i tworzy rekord bazy danych, jeśli to konieczne.
Dokumentacja Lambda
źródło
lambda
trzeba gomap
przerzucićitems
:map(lambda name: MyModel.objects.get_or_create(name = name), items)
Użycie create spowoduje jedno zapytanie na nowy element. Jeśli chcesz zmniejszyć liczbę zapytań INSERT, musisz użyć czegoś innego.
Udało mi się użyć fragmentu wstawiania zbiorczego, mimo że jest on dość stary. Być może konieczne są pewne zmiany, aby ponownie działał.
http://djangosnippets.org/snippets/446/
źródło
Zapoznaj się z tym postem na blogu dotyczącym modułu zbiorczego .
W mojej aplikacji django 1.3 doświadczyłem znacznego przyspieszenia.
źródło
Najłatwiej jest skorzystać z
create
metody Manager, która tworzy i zapisuje obiekt w jednym kroku.for item in items: MyModel.objects.create(name=item.name)
źródło
name
jest unikalny i możliwe są zduplikowane dane wejściowe, dobrym pomysłem byłoby użycieget_or_create
.