Anda tidak dapat membuat hubungan m2m dari objek yang belum disimpan. Jika Anda memiliki pk
s, coba ini:
sample_object = Sample()
sample_object.save()
sample_object.users.add(1,2)
Pembaruan: Setelah membaca jawaban saverio , saya memutuskan untuk menyelidiki masalah ini sedikit lebih mendalam. Inilah temuan saya.
Ini adalah saran asli saya. Ini bekerja, tetapi tidak optimal. (Catatan: Saya menggunakan Bar
s dan a Foo
bukan User
s dan a Sample
, tetapi Anda mendapatkan idenya).
bar1 = Bar.objects.get(pk=1)
bar2 = Bar.objects.get(pk=2)
foo = Foo()
foo.save()
foo.bars.add(bar1)
foo.bars.add(bar2)
Ini menghasilkan total 7 pertanyaan:
SELECT "app_bar"."id", "app_bar"."name" FROM "app_bar" WHERE "app_bar"."id" = 1
SELECT "app_bar"."id", "app_bar"."name" FROM "app_bar" WHERE "app_bar"."id" = 2
INSERT INTO "app_foo" ("name") VALUES ()
SELECT "app_foo_bars"."bar_id" FROM "app_foo_bars" WHERE ("app_foo_bars"."foo_id" = 1 AND "app_foo_bars"."bar_id" IN (1))
INSERT INTO "app_foo_bars" ("foo_id", "bar_id") VALUES (1, 1)
SELECT "app_foo_bars"."bar_id" FROM "app_foo_bars" WHERE ("app_foo_bars"."foo_id" = 1 AND "app_foo_bars"."bar_id" IN (2))
INSERT INTO "app_foo_bars" ("foo_id", "bar_id") VALUES (1, 2)
Saya yakin kita bisa melakukan yang lebih baik. Anda dapat mengirimkan beberapa objek ke add()
metode:
bar1 = Bar.objects.get(pk=1)
bar2 = Bar.objects.get(pk=2)
foo = Foo()
foo.save()
foo.bars.add(bar1, bar2)
Seperti yang bisa kita lihat, melewati beberapa objek menyimpan satu SELECT
:
SELECT "app_bar"."id", "app_bar"."name" FROM "app_bar" WHERE "app_bar"."id" = 1
SELECT "app_bar"."id", "app_bar"."name" FROM "app_bar" WHERE "app_bar"."id" = 2
INSERT INTO "app_foo" ("name") VALUES ()
SELECT "app_foo_bars"."bar_id" FROM "app_foo_bars" WHERE ("app_foo_bars"."foo_id" = 1 AND "app_foo_bars"."bar_id" IN (1, 2))
INSERT INTO "app_foo_bars" ("foo_id", "bar_id") VALUES (1, 1)
INSERT INTO "app_foo_bars" ("foo_id", "bar_id") VALUES (1, 2)
Saya tidak menyadari bahwa Anda juga dapat menetapkan daftar objek:
bar1 = Bar.objects.get(pk=1)
bar2 = Bar.objects.get(pk=2)
foo = Foo()
foo.save()
foo.bars = [bar1, bar2]
Sayangnya, itu menciptakan satu tambahan SELECT
:
SELECT "app_bar"."id", "app_bar"."name" FROM "app_bar" WHERE "app_bar"."id" = 1
SELECT "app_bar"."id", "app_bar"."name" FROM "app_bar" WHERE "app_bar"."id" = 2
INSERT INTO "app_foo" ("name") VALUES ()
SELECT "app_foo_bars"."id", "app_foo_bars"."foo_id", "app_foo_bars"."bar_id" FROM "app_foo_bars" WHERE "app_foo_bars"."foo_id" = 1
SELECT "app_foo_bars"."bar_id" FROM "app_foo_bars" WHERE ("app_foo_bars"."foo_id" = 1 AND "app_foo_bars"."bar_id" IN (1, 2))
INSERT INTO "app_foo_bars" ("foo_id", "bar_id") VALUES (1, 1)
INSERT INTO "app_foo_bars" ("foo_id", "bar_id") VALUES (1, 2)
Mari kita coba menetapkan daftar pk
s, seperti yang disarankan saverio:
foo = Foo()
foo.save()
foo.bars = [1,2]
Karena kami tidak mengambil keduanya Bar
, kami menyimpan dua SELECT
pernyataan, menghasilkan total 5:
INSERT INTO "app_foo" ("name") VALUES ()
SELECT "app_foo_bars"."id", "app_foo_bars"."foo_id", "app_foo_bars"."bar_id" FROM "app_foo_bars" WHERE "app_foo_bars"."foo_id" = 1
SELECT "app_foo_bars"."bar_id" FROM "app_foo_bars" WHERE ("app_foo_bars"."foo_id" = 1 AND "app_foo_bars"."bar_id" IN (1, 2))
INSERT INTO "app_foo_bars" ("foo_id", "bar_id") VALUES (1, 1)
INSERT INTO "app_foo_bars" ("foo_id", "bar_id") VALUES (1, 2)
Dan pemenangnya adalah:
foo = Foo()
foo.save()
foo.bars.add(1,2)
Lulus pk
s untuk add()
memberi kami total 4 pertanyaan:
INSERT INTO "app_foo" ("name") VALUES ()
SELECT "app_foo_bars"."bar_id" FROM "app_foo_bars" WHERE ("app_foo_bars"."foo_id" = 1 AND "app_foo_bars"."bar_id" IN (1, 2))
INSERT INTO "app_foo_bars" ("foo_id", "bar_id") VALUES (1, 1)
INSERT INTO "app_foo_bars" ("foo_id", "bar_id") VALUES (1, 2)
Untuk pengunjung masa depan, Anda dapat membuat objek dan semua objek m2m dalam 2 kueri menggunakan bulk_create di Django 1.4. Catatan bahwa ini hanya dapat digunakan jika Anda tidak memerlukan setiap pra atau pasca-pengolahan data dengan save () metode atau sinyal. Apa yang Anda masukkan persis apa yang akan ada di DB
Anda dapat melakukan ini tanpa menentukan model "through" di lapangan. Untuk kelengkapan, contoh di bawah ini membuat model Pengguna kosong untuk meniru apa yang diminta poster asli.
Sekarang, dalam sebuah shell atau kode lain, buat 2 pengguna, buat objek sampel, dan tambahkan banyak pengguna ke objek sampel itu.
sumber
Django 1.9
Contoh cepat:
sumber
RelatedObjectManagers berbeda "atribut" dari bidang dalam Model. Cara paling sederhana untuk mencapai apa yang Anda cari adalah
Itu sama dengan menetapkan daftar Pengguna, tanpa permintaan tambahan dan pembuatan model.
Jika jumlah kueri yang mengganggu Anda (alih-alih kesederhanaan), maka solusi optimal membutuhkan tiga kueri:
Ini akan berhasil karena kita sudah tahu bahwa daftar 'pengguna' kosong, sehingga kita dapat membuat tanpa berpikir.
sumber
Anda bisa mengganti set objek terkait dengan cara ini (baru di Django 1.9):
sumber
Jika seseorang ingin melakukan jawaban David Marbles pada bidang ManyToMany yang merujuk sendiri. Id dari model through disebut: "to_'model_name_id" dan "from_'model_name'_id".
Jika itu tidak berhasil, Anda dapat memeriksa koneksi Django.
sumber