필드가 많거나 많은 Django 모델의 객체를 만드는 방법은 무엇입니까?
내 모델 :
class Sample(models.Model):
users = models.ManyToManyField(User)
나는 모두를 저장할 user1
와 user2
그 모델 :
user1 = User.objects.get(pk=1)
user2 = User.objects.get(pk=2)
sample_object = Sample(users=user1, users=user2)
sample_object.save()
나는 그것이 틀렸다는 것을 알고 있지만, 내가하고 싶은 것을 얻을 것이라고 확신합니다. 어떻게 하시겠습니까?
저장되지 않은 객체에서 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)
보시다시피 여러 객체를 전달하면 하나가 저장됩니다 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]
불행히도, 그것은 하나의 추가를 만듭니다 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]
두 개를 가져 오지 않기 때문에 두 Bar
개의 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)
For future visitors, you can create an object and all of its m2m objects in 2 queries using the new bulk_create in django 1.4. Note that this is only usable if you don't require any pre or post-processing on the data with save() methods or signals. What you insert is exactly what will be in the DB
You can do this without specifying a "through" model on the field. For completeness, the example below creates a blank Users model to mimic what the original poster was asking.
from django.db import models
class Users(models.Model):
pass
class Sample(models.Model):
users = models.ManyToManyField(Users)
Now, in a shell or other code, create 2 users, create a sample object, and bulk add the users to that sample object.
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)
])
Django 1.9
A quick example:
sample_object = Sample()
sample_object.save()
list_of_users = DestinationRate.objects.all()
sample_object.users.set(list_of_users)
RelatedObjectManagers are different "attributes" than fields in a Model. The simplest way to achieve what you are looking for is
sample_object = Sample.objects.create()
sample_object.users = [1, 2]
That's the same as assigning a User list, without the additional queries and the model building.
If the number of queries is what bothers you (instead of simplicity), then the optimal solution requires three queries:
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)
This will work because we already know that the 'users' list is empty, so we can create mindlessly.
You could replace the set of related objects in this way (new in Django 1.9):
new_list = [user1, user2, user3]
sample_object.related_set.set(new_list)
'development' 카테고리의 다른 글
wpf에서 버튼 테두리를 어떻게 완전히 제거합니까? (0) | 2020.07.06 |
---|---|
디렉토리를 재귀 적으로 만들려면 어떻게해야합니까? (0) | 2020.07.06 |
SDK iOS 8.0의 제품 유형 단위 테스트 번들에는 코드 서명이 필요합니다. (0) | 2020.07.06 |
파이썬에서 16 진수 문자열을 바이트 배열로 (0) | 2020.07.06 |
AppCompat-v7을 사용하여 작업 표시 줄 / 도구 모음에 아이콘 표시 21 (0) | 2020.07.06 |