回答:
保存されていないオブジェクトからm2m関係を作成することはできません。あなたがpk
s を持っているなら、これを試してください:
sample_object = Sample()
sample_object.save()
sample_object.users.add(1,2)
更新:saverioの回答を読んだ後、問題をもう少し詳しく調査することにしました。これが私の発見です。
これは私の最初の提案でした。動作しますが、最適ではありません。(注:Bar
sとaのFoo
代わりにUser
sとa Sample
を使用していますが、あなたはアイデアを理解しています)。
bar1 = Bar.objects.get(pk=1)
bar2 = Bar.objects.get(pk=2)
foo = Foo()
foo.save()
foo.bars.add(bar1)
foo.bars.add(bar2)
合計7つのクエリが生成されます。
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)
私たちはもっとうまくできると確信しています。add()
メソッドに複数のオブジェクトを渡すことができます:
bar1 = Bar.objects.get(pk=1)
bar2 = Bar.objects.get(pk=2)
foo = Foo()
foo.save()
foo.bars.add(bar1, bar2)
ご覧のとおり、複数のオブジェクトを渡すと1つ節約できます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)
オブジェクトのリストを割り当てることもできることを知りませんでした:
bar1 = Bar.objects.get(pk=1)
bar2 = Bar.objects.get(pk=2)
foo = Foo()
foo.save()
foo.bars = [bar1, bar2]
残念ながら、これにより1つの追加が作成されます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)
pk
saverioが提案したように、sのリストを割り当ててみましょう:
foo = Foo()
foo.save()
foo.bars = [1,2]
2つBar
のをフェッチしないので、2つのSELECT
ステートメントを保存し、合計で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)
そして勝者は:
foo = Foo()
foo.save()
foo.bars.add(1,2)
にpk
sをadd()
渡すと、合計4つのクエリが得られます。
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)
将来の訪問者のために、django 1.4の新しいbulk_createを使用して、2つのクエリでオブジェクトとそのすべてのm2mオブジェクトを作成できます。あなたが必要としない場合にのみ使用可能であることに注意してください任意の()メソッドや信号の保存とデータの事前または事後処理を。あなたが挿入するものは正確にDBにあるものです
フィールドで「スルー」モデルを指定せずにこれを行うことができます。完全を期すために、以下の例では、元の投稿者の要求を模倣する空のUsersモデルを作成しています。
from django.db import models
class Users(models.Model):
pass
class Sample(models.Model):
users = models.ManyToManyField(Users)
次に、シェルまたは他のコードで、2人のユーザーを作成し、サンプルオブジェクトを作成して、ユーザーをそのサンプルオブジェクトに一括追加します。
Users().save()
Users().save()
# Access the through model directly
ThroughModel = Sample.users.through
users = Users.objects.filter(pk__in=[1,2])
sample_object = Sample()
sample_object.save()
ThroughModel.objects.bulk_create([
ThroughModel(users_id=users[0].pk, sample_id=sample_object.pk),
ThroughModel(users_id=users[1].pk, sample_id=sample_object.pk)
])
RelatedObjectManagerは、モデルのフィールドとは異なる「属性」です。あなたが探しているものを達成する最も簡単な方法は
sample_object = Sample.objects.create()
sample_object.users = [1, 2]
これは、ユーザーリストを割り当てるのと同じですが、追加のクエリとモデルの作成はありません。
クエリの数が煩わしい場合(単純化ではなく)、最適なソリューションには3つのクエリが必要です。
sample_object = Sample.objects.create()
sample_id = sample_object.id
sample_object.users.through.objects.create(user_id=1, sample_id=sample_id)
sample_object.users.through.objects.create(user_id=2, sample_id=sample_id)
「ユーザー」リストが空であることはすでにわかっているので、これは機能します。