Django에서 ManyToMany 관계에 여러 객체를 한 번에 추가하는 방법은 무엇입니까?


184

Django 문서를 기반으로 여러 객체를 한 번에 전달하여 많은 관계에 추가 할 수 있어야하지만

* TypeError : 해싱 할 수없는 유형 : 'list'

목록에 캐스팅 된 장고 쿼리 세트를 전달하려고합니다. Queryset 또는 ValuesListQueryset 전달도 실패한 것으로 보입니다. for 루프를 사용하는 것보다 더 좋은 방법이 있습니까?

답변:


320

사용 : 설명서에object.m2mfield.add(*items) 설명 된대로 :

add() 목록이 아닌 임의의 수의 인수를 허용합니다.

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

해당 목록을 인수로 확장하려면 *

add(*[obj1, obj2, obj3])

추가:

Django는 obj.save()각 항목을 호출하지 않고 bulk_create()대신을 사용 합니다.


관리자를 보면 객체에 대해 for 루프를 수행하고 저장합니다.
Sam Dolan

3
쉘의 짧은 실험은 @sdolan이 실제로 (현재) 부정확하다는 것을 보여줍니다. 즉, 생성 된 SQL을 볼 때 단일 삽입 문 만 보입니다. INSERT INTO app_one_twos (one_id, two_id) VALUES (1, 1), (1, 2), (1, 3), (1, 4); 이것은 장고 1.4에 있습니다.
Klaas van Schelven

@ KlaasvanSchelven : 생성 된 SQL을 통해 이것을 테스트하는 것을 기억하지는 않지만 내 의견에 따라 소스 코드를 한 눈에 보았습니다. 이것은 2 년 전에 진행되었으므로 상황이 약간 최적화되기를 바랍니다.
Sam Dolan

1
@sdolan 아니요, 개선하지 않았습니다. 방금 테스트 중이었습니다.
Saransh Mohapatra

1
가치 (예 : id)로 이것을 할 수있는 방법이 있습니까? 때로는 객체 목록이 없지만 객체 값 목록 (예 : id)이 있습니까? 오히려 통해 반복하고 또 다른리스트에 모든 개체를 잡는 것보다 ...
DannyMoshe

48

추가하려면 쿼리 세트에서 추가하려는 경우

# 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)

From : ManytoManyfield에 쿼리 셋 결과 삽입


3
이것은 하나 대신 두 개의 쿼리를 수행합니다. (
DylanYoung

2
목록으로 바꿀 필요는 없습니다. add (* permissions)를 직접 수행하십시오.
BjornW

34

Django 1.9는 다 대다 관계에 추가 할 수있는 추가 방법을 추가합니다.

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

set 새로운 멋쟁이입니다.

>>> new_list = [obj1, obj2, obj3]
>>> e.related_set.set(new_list)

2
set항상 거기에 있었다고 생각합니다. e.related_set = new_list이전 Djangos에서 할당 을 통해 작업하는 데 사용한 것과 동일합니다 e.related_set.set(new_list). 그들은 단지 "명시적인 것이 묵시적인 것보다 낫다"는 것을 깨달았습니다.
DylanYoung

1
주의 : 간결하게 설정하면 기존의 모든 관련 모델이 삭제됩니다. 따라서 새로운 객체 목록을 추가하고 기존 객체를 그대로 유지하려면 add (* newlist)를 사용하십시오.
Tasawar Hussain
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.