Membuat objek model secara massal di django

90

Saya memiliki banyak objek untuk disimpan dalam database, jadi saya ingin membuat contoh Model dengan itu.

Dengan django, saya dapat membuat semua contoh model, dengan MyModel(data), dan kemudian saya ingin menyimpan semuanya.

Saat ini, saya memiliki sesuatu seperti itu:

for item in items:
    object = MyModel(name=item.name)
    object.save()

Saya ingin tahu apakah saya dapat menyimpan daftar objek secara langsung, misalnya:

objects = []
for item in items:
    objects.append(MyModel(name=item.name))
objects.save_all()

Bagaimana cara menyimpan semua objek dalam satu transaksi?

Alexis Métaireau
sumber
Tampaknya bola sedang bergulir menerapkan perbaikan untuk kode ini.djangoproject.com/ticket/19527
DanH
1
bertanya-tanya untuk list.save_all? Anda hampir bisa menjawab diri sendiri hanya dengan parafrase yang bertanya-tanya dan menggunakan 2 kata pertama dari pertanyaan topik Anda.
Sławomir Lenart

Jawaban:

95

pada pengembangan django, ada bulk_createsebagai metode manajer objek yang mengambil sebagai masukan larik objek yang dibuat menggunakan konstruktor kelas. lihat dokumen django

ecbtln
sumber
12
Dokumentasi Django untuk bulk_create: docs.djangoproject.com/en/dev/ref/models/querysets/#bulk-create
funkotron
1
Tapi ingat bulk_create memiliki beberapa batasan seperti itu tidak membuat kunci utama jika itu adalah AutoField yang save () secara otomatis.
Hitesh Garg
@HiteshGarg, Apakah itu masih benar sekarang?
Raydel Miranda
1
@RaydelMiranda, iya masih benar. Itu ada di dalam dokumentasi:If 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).
interDist
1
Menggunakan Django 3.0.x dan saya mengkonfirmasi bahwa penggunaan bulk_create()tidak memicu sinyal apapun. Kenapa ya.
enchance
42

Gunakan bulk_create()metode. Ini standar di Django sekarang.

Contoh:

Entry.objects.bulk_create([
    Entry(headline="Django 1.0 Released"),
    Entry(headline="Django 1.1 Announced"),
    Entry(headline="Breaking: Django is awesome")
])
Danil
sumber
1
Berubah di Django 1.10: Dukungan untuk menyetel kunci utama pada objek yang dibuat menggunakan bulk_create () saat menggunakan PostgreSQL ditambahkan.
elad perak
4

bekerja bagi saya untuk menggunakan penanganan transaksi manual untuk loop (postgres 9.1):

from django.db import transaction
with transaction.commit_on_success():
    for item in items:
        MyModel.objects.create(name=item.name)

sebenarnya ini tidak sama, seperti penyisipan massal database 'asli', tetapi memungkinkan Anda untuk menghindari / menurunkan transportasi / operasi orms / biaya analisis kueri sql

eviltnan
sumber
1
Ini sedikit berubah. Sekarang transaksi tidak ada commit_on_successlagi. Anda harus menggunakan transaction.atomic()See: stackoverflow.com/questions/21861207/…
t_io
4

Berikut adalah cara membuat entitas secara massal dari file yang dipisahkan kolom, mengesampingkan semua rutinitas unquoting dan un-escape:

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)
Ivan Klass
sumber
3

untuk implementasi baris tunggal, Anda bisa menggunakan ekspresi lambda di peta

map(lambda x:MyModel.objects.get_or_create(name=x), items)

Di sini, lambda mencocokkan setiap item dalam daftar item dengan x dan membuat rekaman Database jika perlu.

Dokumentasi Lambda

FallenAngel
sumber
Anda mungkin ingin menyebutkan bahwa lambdaharus mapped lebih items:map(lambda name: MyModel.objects.get_or_create(name = name), items)
Manoj Govindan
Ya, itu cara lain yang saya coba katakan (:
FallenAngel
2

Menggunakan create akan menyebabkan satu kueri per item baru. Jika Anda ingin mengurangi jumlah query INSERT, Anda harus menggunakan yang lain.

Saya telah cukup berhasil menggunakan cuplikan Penyisipan Massal, meskipun cuplikan tersebut cukup lama. Mungkin ada beberapa perubahan yang diperlukan untuk membuatnya berfungsi kembali.

http://djangosnippets.org/snippets/446/

OmerGertel
sumber
2

Lihat posting blog ini pada modul bulkops .

Pada aplikasi django 1.3 saya, saya mengalami percepatan yang signifikan.

MrJ
sumber
-19

Cara termudah adalah dengan menggunakan createmetode Manajer, yang membuat dan menyimpan objek dalam satu langkah.

for item in items:
    MyModel.objects.create(name=item.name)
Daniel Roseman
sumber
+1. Jika nameinput unik dan duplikat dimungkinkan maka akan menjadi ide yang baik untuk digunakan get_or_create.
Manoj Govindan
16
Bagaimana ini menjawab pertanyaan? Model.objects.create sama dengan object = MoModel (..) object.save (). Dan ini tidak melakukannya dalam satu transaksi ...
automagic