如何修改查询集并将其保存为新对象?

Posted

技术标签:

【中文标题】如何修改查询集并将其保存为新对象?【英文标题】:How to modify a queryset and save it as new objects? 【发布时间】:2013-04-15 12:25:50 【问题描述】:

我需要为特定模型查询一组对象,更改单个属性/列(“帐户”),然后将整个查询集的对象保存为新对象/行。换句话说,我想复制对象,并在副本上更改一个属性(“帐户”)。我基本上是在创建一个新帐户,然后遍历每个模型并将先前帐户的对象复制到新帐户,因此我将使用不同的模型重复执行此操作,可能使用 django shell。我应该如何处理这个?可以在查询集级别完成还是我需要遍历所有对象?

即,

MyModel.objects.filter(account="acct_1")
# Now I need to set account = "acct_2" for the entire queryset, 
# and save as new rows in the database

【问题讨论】:

我想我很困惑。是否要复制对象并为其设置新帐户? 是的。抱歉,我会尝试改写它以使其更清楚。 可以批量更新,也可以批量插入,但不能批量更新和单行新建。您必须遍历查询集。 谢谢,@JoshSmeaton。看起来 bozdoz 的答案是要走的路。 【参考方案1】:

来自docs:

如果对象的主键属性没有设置,或者设置了但是一个 记录不存在,Django 执行 INSERT。

因此,如果您将 idpk 设置为 None,它应该可以工作,但我在 SO:Duplicating model instances and their related objects in Django / Algorithm for recusrively duplicating an object 上看到了对此解决方案的相互矛盾的回应

这个解决方案应该可以工作(感谢@JoshSmeaton 的修复):

models = MyModel.objects.filter(account="acct_1")
for model in models:
  model.id = None
  model.account = "acct_2"
  model.save()

我认为,就我而言,我正在测试的模型上有一个OneToOneField,所以我的测试不适用于这个基本解决方案是有道理的。但是,我相信它应该可以工作,只要你照顾好 OneToOneField 的。

【讨论】:

但是这样会保存旧对象,不是吗? 是的。我被这个问题弄糊涂了。道歉@BenRoberts 这将覆盖该字段。 您只需将 id 设置为 None,我已经更新了您的答案。 在我的 django 版本中不起作用,但我从其他问题中看到它应该在其他版本中起作用:***.com/questions/4733609/…

以上是关于如何修改查询集并将其保存为新对象?的主要内容,如果未能解决你的问题,请参考以下文章

编辑文件上的数据并将其保存为新文件而不是覆盖它

访问:如何执行查询并将其结果保存在报告中

Laravel Eloquent:获取嵌套关系中的数据总和并将其添加为新属性

如何获取 ADLS Gen2 文件的最后修改日期并将其保存到 python 中的 csv

如何在查询中使用 $push 将数据插入子文档,而不是检索文档并将其保存回来

如何序列化对象并将其保存到 Android 中的文件中?