如何修改查询集并将其保存为新对象?
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。
因此,如果您将 id
或 pk
设置为 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