【问题标题】:Is there a way to update a foreign key field using an SQL Update Query in Django有没有办法在 Django 中使用 SQL 更新查询来更新外键字段
【发布时间】:2021-05-17 17:25:16
【问题描述】:

我有两个班级,我正在尝试尽可能有效地将一个字段从一个字段移动到另一个字段。数据库很大,所以如果我们可以在 Django 中使用 SQL Update query 或直接 SQL 查询,那将是理想的选择。我的数据库是 PostgreSQL。

Class Order(models.Model):
    name = models.TextField(null=True, blank=True)
    address = models.ForeignKey(Address, on_delete=models.PROTECT)

Class Address(models.Model):
    name = models.TextField(null=True, blank=True)

我知道我可以手动执行此操作,但我希望能够像这样运行 SQL 更新查询:

Order.objects.all().update(address__name=F('name'))

但我无法使用 update 命令更新外键字段。任何关于 Django 或直接在 SQL 中的替代方案的建议 - 而不是仅仅写出以下内容 - 表示赞赏。

for order in Order.objects.all():
    address = order.address
    address.name = order.name
    address.save()

【问题讨论】:

  • 您的用例意味着对于一个地址模型将只有一个订单,反之亦然。在这种情况下,您不应该使用OneToOneField 吗?否则,您的用例没有意义,因为您最终可能会多次更新地址。还有为什么要存储重复数据?在这种情况下,名称不应该只出现在其中一个模型中吗?
  • @AbdulAzizBarkat 是的,理想情况下该类将使用OneToOneField,尽管在我目前的情况下它没有。另外,为了方便name字段的转移,两个型号上都有名字,之后可以去掉名字字段。

标签: python django postgresql


【解决方案1】:

这个怎么样:

orders = Order.objects.select_related('address')
addresses = []
for order in orders:
    address = order.address
    address.name = order.name
    addresses.append(address)
Address.objects.bulk_update(addresses, ['name'])

这应该只进行 2 个 SQL 查询

但定义不明确,因为一个地址可以附加多个订单

【讨论】:

  • 因此,在这种情况下,select_related 删除了 order.address 预期的额外查询,bulk_update 阻止保存每个单独的地址,对吗?这是一个很好的解决方案,感谢@Pawel。
  • 正确 :) 您可以打开使用 Django 调试工具栏的查询记录来检查查询
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-16
  • 2019-06-28
  • 2014-08-13
  • 1970-01-01
  • 2017-04-30
  • 2011-03-04
  • 2020-12-22
相关资源
最近更新 更多