【问题标题】: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 的答案是要走的路。

标签: django django-queryset


【解决方案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 版本中不起作用,但我从其他问题中看到它应该在其他版本中起作用:stackoverflow.com/questions/4733609/…
猜你喜欢
  • 2015-09-08
  • 2012-02-12
  • 2022-06-16
  • 1970-01-01
  • 2019-12-19
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
相关资源
最近更新 更多