Làm cách nào để thêm nhiều đối tượng vào mối quan hệ ManyToMany cùng một lúc trong Django?


184

Dựa trên tài liệu Django, tôi sẽ có thể vượt qua nhiều đối tượng cùng một lúc để được thêm vào mối quan hệ nhiều người nhưng tôi nhận được một

* TypeError: loại không thể xóa: 'list'

khi tôi cố gắng vượt qua một bộ truy vấn django được chọn trong một danh sách. Việc vượt qua một Queryset hoặc ValuesListQueryset dường như cũng thất bại. Có cách nào tốt hơn là sử dụng vòng lặp for không?

Câu trả lời:


320

Sử dụng: object.m2mfield.add(*items)như được mô tả trong tài liệu :

add() chấp nhận một số lượng đối số tùy ý, không phải là danh sách của chúng.

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

Để mở rộng danh sách đó thành đối số, hãy sử dụng *

add(*[obj1, obj2, obj3])

Phụ lục:

Django không gọi obj.save()cho từng mục mà bulk_create()thay vào đó sử dụng .


Nếu bạn nhìn vào trình quản lý, nó chỉ thực hiện một vòng lặp for trên các đối tượng và các cuộc gọi lưu vào chúng.
Sam Dolan

3
Một thử nghiệm ngắn từ shell cho thấy @sdolan trên thực tế (hiện tại) không chính xác. Tức là khi tôi nhìn vào SQL được tạo, tôi chỉ thấy một câu lệnh chèn duy nhất: INSERT INTO app_one_twos (one_id, Two_id) VALUES (1, 1), (1, 2), (1, 3), (1, 4); Đây là trong Django 1.4.
Klaas van Schelven

@KlaasvanSchelven: Tôi không nhớ đã thử nghiệm điều này thông qua sql được tạo, nhưng dựa trên nhận xét của tôi, tôi khá chắc chắn rằng tôi chỉ lướt qua mã nguồn. Hãy nhớ rằng điều này đã hơn 2 năm trước, vì vậy tôi sẽ hy vọng rằng mọi thứ đã được tối ưu hóa một chút.
Sam Dolan

1
@sdolan Không có họ đã không cải thiện nó. Tôi chỉ đang thử nghiệm nó.
Saransh Mohapatra

1
Bất kỳ cách nào để làm điều này theo giá trị (ví dụ: id)? Đôi khi bạn không có danh sách các đối tượng nhưng danh sách các giá trị đối tượng (ví dụ: id)? Thay vì lặp đi lặp lại và chộp lấy tất cả các đối tượng vào một danh sách khác ...
DannyMoshe

48

Để thêm vào, nếu bạn muốn thêm chúng từ bộ truy vấn

Thí dụ

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

Từ: Chèn kết quả truy vấn vào ManytoManyfield


3
Điều này thực hiện hai truy vấn thay vì một :(
DylanYoung

2
Lưu ý rằng bạn không cần phải biến nó thành một danh sách. Chỉ cần thêm (* quyền) trực tiếp.
BjornW

34

Django 1.9 bổ sung các cách bổ sung để thêm vào mối quan hệ nhiều-nhiều.

Tài liệu: https://docs.djangoproject.com/en/dev/ref/models/relations/#django.db.models.fields.related.RelatedManager.set

set là một tính mới

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

2
settôi luôn ở đó Chỉ là nó được sử dụng để làm việc thông qua sự phân công e.related_set = new_listtrong Djangos cũ là tương đương với e.related_set.set(new_list). Họ chỉ nhận ra rằng "rõ ràng là tốt hơn ngầm".
DylanYoung

1
Thận trọng: Để ngắn gọn, hãy xóa tất cả các mô hình liên quan hiện có. Vì vậy, nếu bạn muốn thêm danh sách các đối tượng mới và muốn giữ nguyên đối tượng hiện có, hãy sử dụng add (* danh sách mới)
Tasawar Hussain
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.