【问题标题】:Django object creation and Postgres SequencesDjango 对象创建和 Postgres 序列
【发布时间】:2010-01-18 18:21:46
【问题描述】:

我有一个导入脚本,它运行一系列命令以将内容从一个 Postgres DB 获取到另一个,两者都运行相同的 Django 代码库。在大多数情况下,它使用 ./manage.py loaddata 进行复制,但有些对象需要额外处理,我在自定义脚本中使用 Django 的 objects.create() 方法来复制数据。执行此操作时,我指定 ID,即

MyObject.objects.create(id = 2, title = 'foo')

脚本完成后,我注意到 Postgres SEQUENCE 在我执行 objects.create() 的表上是错误的。即,导入前是 50,导入后仍然是 50,即使表现在有 150 个对象。当然,这会在创建新对象时导致错误,因为它会尝试使用已经存在的 ID(在所有这些表中,ID 只是一个普通的自动增量字段)。但是,通过 ./manage.py loaddata 填充的表看起来还不错。

我知道我可以使用 Django 的 ./manage.py sqlsequenreset 手动重置这些表,但我很好奇为什么序列似乎一开始就失控了。 objects.create() 不会增加它吗?我是否忽略了一些明显的东西?

【问题讨论】:

  • 没有更好的方法来同步数据库吗?您是否检查了关于 id 字段中的自动增量的表结构?
  • 我不是最新的 postgres 特定的东西,但我的猜测是,每当插入带有 null 标识列的行时,它都会被 postgres“填充”( a la auto_increment) 并且序列递增。如果你自己指定一个id,它会绕过这个逻辑,直接插入行。我猜,django 并没有尝试实际增加序列号,而是将其留给数据库引擎。
  • @shylent 我在这里也很凭直觉,但似乎在数据库中增加一个序列变量的目的是避免必须在每个记录的每个记录上运行一个最大值未指定 id 时插入。为了在 OP 的用例中保持序列是最新的,当指定 id 时,必须在每次插入之后运行一个最大值。我认为要求用户手动请求刷新是合理的。

标签: django postgresql


【解决方案1】:

一切正常。 django 的 create() 直接与序列启动无关。简要说明:

  • postgresql 自动递增 ('serial' type) 只是一个快捷方式 '创建序列+创建整数 以序列值为默认值的字段'
  • django 的自动字段主键(id 如果您未指定,则为整数) 只需创建一个串行字段
  • 当您手动指定 id 时, postgres 将值插入 数据库。当您指定一个值时, 它省略了“默认”参数, 这是正确的行为。

因此,如果您希望插入以您选择的方式递增序列,则需要使用 SELECT setval('sequence_name', int_value); 手动更改序列值。否则将其保留为 null,它将自动递增 - 选择当前 val 并将其递增 +1(如果未在序列定义中指定不同)。

另一个想法是创建对象,然后更新 id(当然它不能已经使用),最后将序列值设置为最大 id。

【讨论】:

    【解决方案2】:

    自动增量字段有效,但你必须像这样进行查询

    MyObject.objects.create(title='foo')
    

    没有 id 字段,这是使用数据库自​​动计算的。

    【讨论】:

    • 我想我在这里很好奇的是 Django 自己的 dumpdata 命令生成的 JSON 指定了对象的 PK,而 loaddata 命令似乎尊重这些 PK,而 Postgre 序列没有弄乱.那么为什么 objects.create 不能这样做呢?也许这只是一个疏忽?
    • @KRH 我认为django/core/management/commands/load.py:188 中的这段代码可以解释我们这个问题。
    • 知道了。考虑到它可能产生的主键错误,我想我有点惊讶 objects.create() 没有这样做,但我想从设计的角度来看,他们认为这是用户要解决的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-17
    • 1970-01-01
    相关资源
    最近更新 更多