Sie können keine m2m-Beziehungen aus nicht gespeicherten Objekten erstellen. Wenn Sie das pk
s haben, versuchen Sie dies:
sample_object = Sample()
sample_object.save()
sample_object.users.add(1,2)
Update: Nachdem ich die Antwort des Sparers gelesen hatte , beschloss ich, das Problem etwas eingehender zu untersuchen. Hier sind meine Ergebnisse.
Dies war mein ursprünglicher Vorschlag. Es funktioniert, ist aber nicht optimal. (Hinweis: Ich verwende Bar
s und a Foo
anstelle von User
s und a Sample
, aber Sie haben die Idee).
bar1 = Bar.objects.get(pk=1)
bar2 = Bar.objects.get(pk=2)
foo = Foo()
foo.save()
foo.bars.add(bar1)
foo.bars.add(bar2)
Es werden insgesamt 7 Abfragen generiert:
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)
Ich bin sicher, wir können es besser machen. Sie können mehrere Objekte an die add()
Methode übergeben:
bar1 = Bar.objects.get(pk=1)
bar2 = Bar.objects.get(pk=2)
foo = Foo()
foo.save()
foo.bars.add(bar1, bar2)
Wie wir sehen können, spart das Übergeben mehrerer Objekte eines 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)
Mir war nicht bewusst, dass Sie auch eine Liste von Objekten zuweisen können:
bar1 = Bar.objects.get(pk=1)
bar2 = Bar.objects.get(pk=2)
foo = Foo()
foo.save()
foo.bars = [bar1, bar2]
Leider schafft das eine zusätzliche 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)
Versuchen wir, eine Liste von pk
s zuzuweisen , wie von saverio vorgeschlagen:
foo = Foo()
foo.save()
foo.bars = [1,2]
Da wir die beiden Bar
s nicht abrufen , speichern wir zwei SELECT
Anweisungen, was insgesamt 5 ergibt:
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)
Und der Gewinner ist:
foo = Foo()
foo.save()
foo.bars.add(1,2)
Wenn Sie pk
s an übergeben add()
, erhalten Sie insgesamt 4 Abfragen:
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)
Für zukünftige Besucher können Sie ein Objekt und alle seine m2m-Objekte in 2 Abfragen mit dem neuen Bulk_Create in Django 1.4 erstellen. Beachten Sie, dass dies nur verwendet werden kann, wenn Sie keine Vor- oder Nachbearbeitung der Daten mit save () -Methoden oder -Signalen benötigen . Was Sie einfügen, ist genau das, was in der DB sein wird
Sie können dies tun, ohne ein "Durch" -Modell auf dem Feld anzugeben. Der Vollständigkeit halber erstellt das folgende Beispiel ein leeres Benutzermodell, um die Anforderungen des Originalplakats nachzuahmen.
Erstellen Sie nun in einer Shell oder einem anderen Code zwei Benutzer, erstellen Sie ein Beispielobjekt und fügen Sie die Benutzer in großen Mengen zu diesem Beispielobjekt hinzu.
quelle
Django 1.9
Ein kurzes Beispiel:
quelle
RelatedObjectManager sind andere "Attribute" als Felder in einem Modell. Der einfachste Weg, um das zu erreichen, wonach Sie suchen, ist
Dies entspricht dem Zuweisen einer Benutzerliste ohne die zusätzlichen Abfragen und die Modellbildung.
Wenn Sie die Anzahl der Abfragen stört (anstelle der Einfachheit), erfordert die optimale Lösung drei Abfragen:
Dies funktioniert, da wir bereits wissen, dass die Benutzerliste leer ist, sodass wir sinnlos erstellen können.
quelle
Sie können den Satz verwandter Objekte auf diese Weise ersetzen (neu in Django 1.9):
quelle
Wenn jemand nach David Marbles sucht, antworten Sie auf ein selbstverweisendes ManyToMany-Feld. Die IDs des Durchgangsmodells heißen: "to_'model_name_id" und "from_'model_name'_id".
Wenn das nicht funktioniert, können Sie die Django-Verbindung überprüfen.
quelle