【问题标题】:Using self.id in other field with one query通过一个查询在其他字段中使用 self.id
【发布时间】:2012-01-23 00:17:32
【问题描述】:

诚然,这与我之前问过的this one 非常相似,但是,如果能得到答案,那就太好了。

我想通过使用主键来填充另一个字段来创建一个实例。 Yuji Tomita 提出了一个使用两个查询的解决方案(顺便说一句,它工作得很好),但我想知道是否可以只使用一个查询来完成。

富田裕二的解决办法:

def save(self, *args, **kwargs):
    add = not self.pk
    super(MyModel, self).save(*args, **kwargs)
    if add:
        self.identification = str(self.id)
        kwargs['force_insert'] = False # create() uses this, which causes error.
        super(MyModel, self).save(*args, **kwargs)

提前致谢。

【问题讨论】:

  • 如何在 SQL 插入期间引用自动生成的 ID? 可能有助于解决这个问题。观看!
  • 为什么需要单独存储“标识”?
  • @Yuji:是的,这将是一个很好的重申。
  • @Thomas 说来话长,但假设我想利用 Django 的 id 字段的自动增量功能。如果您要问我正在寻找的最终结果,那是 Joomla 的嵌套 cmets(1、2、... 用于父母,1.1、1.2 用于 1 的孩子,1.1.1 等用于孩子的孩子)。标识包含这些字符串。
  • 据我所知,对于使用原始 SQL(以及其中的麻烦),您不能对此代码进行少于 2 次查询。但是,如果您希望嵌套 cmets 轻松工作,我建议使用 django-treebeard 来管理层次结构。

标签: django save


【解决方案1】:

如果您的主键是一个自动递增的整数,您可以通过在 db shell 中运行 SELECT MAX(id) FROM myTable 来计算下一个键;或在 Django 中:

from django.db.models import Max
next_key = MyTable.objects.aggregate(next=Max('id'))['next']+1

这种方法的问题是您必须实现行锁定;否则另一个进程可能会添加到数据库中 - 获取下一个 ID 值,这将导致 your 代码给出IntegrityError 异常;它并不能解决您的“两个查询”挑战。

更好的解决方案是使用非顺序主键。这通常是UUID。在 MySQL 中,您可以使用 UUID() 函数作为主键。这保证(合理地)没有冲突并且是唯一的。

在 Django 中没有官方支持 UUID 字段(patch 已提交),但有 lots of examples 可以使用。

如果你走这条路,那么你可以在任何时候生成一个主键,然后将其分配给模型而不执行查询。

【讨论】:

  • 这很有趣,但既不能解决问题,也不能解决所述用例。
猜你喜欢
  • 2012-02-12
  • 2020-05-06
  • 2018-03-06
  • 2014-12-31
  • 1970-01-01
  • 1970-01-01
  • 2017-04-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多