Bagaimana cara menambahkan banyak objek ke hubungan ManyToMany sekaligus di Django?

185

Berdasarkan pada dokumen Django, saya harus dapat melewati beberapa objek sekaligus untuk ditambahkan ke hubungan manytomany tapi saya mendapatkan

* TypeError: tipe yang tidak dapat ditemukan: 'list'

ketika saya mencoba untuk melewati queryset Django yang dicantumkan dalam daftar. Melewati Queryset atau ValuesListQueryset tampaknya gagal juga. Apakah ada cara yang lebih baik daripada menggunakan for for?

philgo20
sumber

Jawaban:

320

Gunakan: object.m2mfield.add(*items)seperti yang dijelaskan dalam dokumentasi :

add() menerima sejumlah argumen sewenang-wenang, bukan daftar dari mereka.

add(obj1, obj2, obj3, ...)

Untuk memperluas daftar itu menjadi argumen, gunakan *

add(*[obj1, obj2, obj3])

Tambahan:

Django tidak memanggil obj.save()untuk setiap item tetapi menggunakan bulk_create(), sebagai gantinya.

Yuji 'Tomita' Tomita
sumber
Jika Anda melihat manajer itu hanya melakukan perulangan untuk objek dan panggilan menyimpannya.
Sam Dolan
3
Eksperimen singkat dari shell menunjukkan bahwa @sdolan sebenarnya (saat ini) salah. Yaitu ketika saya melihat SQL yang dihasilkan, saya hanya melihat satu pernyataan penyisipan: INSERT INTO app_one_twos (one_id, two_id) VALUES (1, 1), (1, 2), (1, 2), (1, 3), (1, 4); Ini dalam Django 1.4.
Klaas van Schelven
@KlaasvanSchelven: Saya tidak ingat menguji ini melalui sql yang dihasilkan, tetapi berdasarkan komentar saya, saya cukup yakin saya hanya melirik kode sumber. Perlu diingat bahwa ini sudah lebih dari 2 tahun yang lalu, jadi saya berharap semuanya telah dioptimalkan sedikit.
Sam Dolan
1
@dolan Tidak, mereka belum memperbaikinya. Saya hanya mengujinya.
Saransh Mohapatra
1
Adakah cara untuk melakukan ini berdasarkan nilai (mis. Id)? Terkadang Anda tidak memiliki daftar objek tetapi daftar nilai objek (mis. Id)? Daripada berputar-putar dan mengambil semua benda ke dalam daftar lain ...
DannyMoshe
48

Untuk menambahkan, Jika Anda ingin menambahkannya dari queryset

Contoh

# Returns a queryset
permissions = Permission.objects.all()

# Add the results to the many to many field (notice the *)

group = MyGroup.objects.get(name='test')

group.permissions.add(*permissions)

Dari: Masukkan hasil queryset ke ManytoManyfield

Dr Manhattan
sumber
3
Ini melakukan dua pertanyaan alih-alih satu :(
DylanYoung
2
Perhatikan bahwa Anda tidak perlu mengubahnya menjadi daftar. Cukup tambahkan (* izin) secara langsung.
BjornW
34

Django 1.9 menambahkan cara-cara tambahan untuk menambah hubungan banyak ke banyak.

Dokumentasi: https://docs.djangoproject.com/en/dev/ref/models/relations/#django.db.models.fields.related.RelatedManager.set

set adalah kebaikan baru:

>>> new_list = [obj1, obj2, obj3]
>>> e.related_set.set(new_list)
aero
sumber
2
setselalu ada di sana saya pikir. Hanya saja itu digunakan untuk bekerja melalui penugasan e.related_set = new_listdi Djangos lama setara dengan e.related_set.set(new_list). Mereka baru menyadari bahwa "eksplisit lebih baik daripada implisit".
DylanYoung
1
Perhatian: Agar ringkas, atur hapus semua model terkait yang ada. Jadi, jika Anda ingin menambah daftar objek baru dan ingin tetap ada yang sudah ada, gunakan add (* newlist)
Tasawar Hussain