如何在 Django 中一次将多个对象添加到 ManyToMany 关系?
Posted
技术标签:
【中文标题】如何在 Django 中一次将多个对象添加到 ManyToMany 关系?【英文标题】:How to add multiple objects to ManyToMany relationship at once in Django ? 【发布时间】:2011-06-24 23:24:13 【问题描述】:基于 Django 文档,我应该能够一次传递多个对象以添加到多对多关系中,但我得到了一个
* TypeError: unhashable type: 'list'
当我尝试传递一个列表中的 django 查询集时。传递 Queryset 或 ValuesListQueryset 似乎也失败了。有没有比使用 for 循环更好的方法?
【问题讨论】:
【参考方案1】:使用:object.m2mfield.add(*items)
,如documentation 中所述:
add()
接受任意数量的参数,而不是它们的列表。
add(obj1, obj2, obj3, ...)
要将列表扩展为参数,请使用*
add(*[obj1, obj2, obj3])
附录:
Django 不会为每个项目调用obj.save()
,而是使用bulk_create()
。
【讨论】:
如果您查看管理器,它只会对对象执行 for 循环并调用它们的保存。 shell 的一个简短实验表明@sdolan 实际上(当前)是不正确的。 IE。当我查看生成的 SQL 时,我只看到一个插入语句: INSERT INTO app_one_twos (one_id, two_id) VALUES (1, 1), (1, 2), (1, 3), (1, 4);这是在 Django 1.4 中。 @KlaasvanSchelven:我不记得通过生成的 sql 进行了测试,但根据我的评论,我很确定我只是看了一眼源代码。请记住,这是 2 年前的事了,所以我希望事情已经优化了一点。 @sdolan 不,他们没有改进它。我只是在测试它。 有什么方法可以按值(例如 id)做到这一点?有时您没有对象列表,而是对象值列表(即 id)?而不是循环遍历并将所有对象抓取到另一个列表中......【参考方案2】:添加,如果你想从查询集中添加它们
例子
# 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)
发件人:Insert queryset results into ManytoManyfield
【讨论】:
这执行两个查询而不是一个:( 请注意,您不需要将其转换为列表。直接添加(*permissions)即可。 谢谢兄弟。这真的对我有帮助。我试图通过subject = Subject.objects.filter(connect_class=class_list)
。我做了student_data.subject.add(*subject)
,它奏效了。【参考方案3】:
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)
【讨论】:
set
我想一直都在那里。只是它过去在旧 Django 中通过赋值 e.related_set = new_list
等效于 e.related_set.set(new_list)
。他们刚刚意识到“显式胜于隐式”。
注意:为简洁起见,set 删除所有现有的关联模型。因此,如果您想添加新对象列表并希望保持现有对象不变,请使用 add(*newlist)
当您想将记录更新到新集合时,此解决方案非常棒,并且如果对象已经在集合“obj1”中,那么数据库中的记录不会重新创建。
在当前 Django 版本 (3.2.6) 中工作方式相同以上是关于如何在 Django 中一次将多个对象添加到 ManyToMany 关系?的主要内容,如果未能解决你的问题,请参考以下文章
是否可以在 C# winforms 中一次将文本写入多个文本框?