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?


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



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")
])

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


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)

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


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/


2

Lihat posting blog ini pada modul bulkops .

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


-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)

+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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.