【问题标题】:Getting Django migration error "sequence must have same owner as table it is linked to", but all tables and sequences have the same owner获取 Django 迁移错误“序列必须与其链接的表具有相同的所有者”,但所有表和序列都具有相同的所有者
【发布时间】:2022-01-18 19:57:44
【问题描述】:

我正在尝试在 Django 项目中运行迁移。 (Django 3.1,Python 3.9.9)我在我的虚拟环境中。我不断收到一个令人费解的错误。

 python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, intake, sessions
Running migrations:
  Applying intake.0021_auto_20220115_1147...Traceback (most recent call last):
  File "/Users/me/Sites/client/venv/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
psycopg2.errors.ObjectNotInPrerequisiteState: sequence must have same owner as table it is linked to

但是当我列出我的表和序列时,它们都有相同的所有者。

intake=# \dt
                    List of relations
 Schema |            Name            | Type  |   Owner   
--------+----------------------------+-------+-----------
 public | auth_group                 | table | dbuser
 public | auth_group_permissions     | table | dbuser
 public | auth_permission            | table | dbuser
 public | auth_user                  | table | dbuser
 public | auth_user_groups           | table | dbuser
 public | auth_user_user_permissions | table | dbuser
 public | django_admin_log           | table | dbuser
 public | django_content_type        | table | dbuser
 public | django_migrations          | table | dbuser
 public | django_session             | table | dbuser
 public | intake_byattorney          | table | dbuser
 public | intake_client              | table | dbuser
(12 rows)

intake=# \ds
                         List of relations
 Schema |               Name                |   Type   |   Owner   
--------+-----------------------------------+----------+-----------
 public | auth_group_id_seq                 | sequence | dbuser
 public | auth_group_permissions_id_seq     | sequence | dbuser
 public | auth_permission_id_seq            | sequence | dbuser
 public | auth_user_groups_id_seq           | sequence | dbuser
 public | auth_user_id_seq                  | sequence | dbuser
 public | auth_user_user_permissions_id_seq | sequence | dbuser
 public | django_admin_log_id_seq           | sequence | dbuser
 public | django_content_type_id_seq        | sequence | dbuser
 public | django_migrations_id_seq          | sequence | dbuser
 public | intake_byattorney_id_seq          | sequence | dbuser
 public | intake_client_id_seq              | sequence | dbuser
(11 rows)

为什么会这样?我是否需要将表和序列的所有权更改为其他内容,例如 postgres

这发生在本地和我的生产机器上。

以下是相关迁移的内容:


from django.db import migrations, models


class Migration(migrations.Migration):

    dependencies = [
        ('intake', '0020_alter_client_status'),
    ]

    operations = [
        migrations.AlterField(
            model_name='byattorney',
            name='id',
            field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
        ),
        migrations.AlterField(
            model_name='client',
            name='id',
            field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
        ),
        migrations.AlterField(
            model_name='client',
            name='status',
            field=models.CharField(choices=[('1__intake', 'Stage 1: Needs initial contact'), ('2__attorney-review', 'Stage 2: Needs attorney contact'), ('3__evaluation', 'Stage 3: Evaluation - Accept/Reject'), ('4__final-disposition', 'Stage 4: Final Disposition'), ('5__client-accepted', 'Client Accepted'), ('6__client-rejected', 'Client Rejected')], max_length=20),
        ),
    ]

这里是`python manage.py sqlmigrate carry 0021'的输出:

python manage.py sqlmigrate intake 0021
BEGIN;
--
-- Alter field id on byattorney
--
SET CONSTRAINTS "intake_client_by_attorney_id_680583a2_fk" IMMEDIATE; ALTER TABLE "intake_client" DROP CONSTRAINT "intake_client_by_attorney_id_680583a2_fk";
ALTER TABLE "intake_byattorney" ALTER COLUMN "id" TYPE integer USING "id"::integer;
DROP SEQUENCE IF EXISTS "intake_byattorney_id_seq" CASCADE;
CREATE SEQUENCE "intake_byattorney_id_seq";
ALTER TABLE "intake_byattorney" ALTER COLUMN "id" SET DEFAULT nextval('"intake_byattorney_id_seq"');
SELECT setval('"intake_byattorney_id_seq"', MAX("id")) FROM "intake_byattorney";
ALTER SEQUENCE "intake_byattorney_id_seq" OWNED BY "intake_byattorney"."id";
ALTER TABLE "intake_client" ALTER COLUMN "by_attorney_id" TYPE integer USING "by_attorney_id"::integer;
ALTER TABLE "intake_client" ADD CONSTRAINT "intake_client_by_attorney_id_680583a2_fk" FOREIGN KEY ("by_attorney_id") REFERENCES "intake_byattorney" ("id") DEFERRABLE INITIALLY DEFERRED;
--
-- Alter field id on client
--
ALTER TABLE "intake_client" ALTER COLUMN "id" TYPE integer USING "id"::integer;
DROP SEQUENCE IF EXISTS "intake_client_id_seq" CASCADE;
CREATE SEQUENCE "intake_client_id_seq";
ALTER TABLE "intake_client" ALTER COLUMN "id" SET DEFAULT nextval('"intake_client_id_seq"');
SELECT setval('"intake_client_id_seq"', MAX("id")) FROM "intake_client";
ALTER SEQUENCE "intake_client_id_seq" OWNED BY "intake_client"."id";
--
-- Alter field status on client
--
COMMIT;

【问题讨论】:

  • 能分享一下迁移文件intake.0021_auto_20220115_1147的内容吗?
  • @IainShelvington:感谢您的建议。我已编辑问题以包含迁移的内容。
  • 看起来迁移正在改变您的几个id 字段,这是预期的,您改变了什么?您能否运行python manage.py sqlmigrate intake 0021 并将输出添加到问题中,您可以了解 Django 正在尝试运行的实际 SQL。您最近是否更改了数据库设置?
  • 谢谢,不知道那个。我将它添加到问题中。我确实认为这很奇怪,前两个迁移变化;我没有看到相应的代码更改来解释它们。第三个反映了我正在尝试做的事情,即使状态可以按任意顺序而不是按字母顺序排序。是否可以编辑或跳过迁移,还是我只是自找麻烦?
  • 您可以删除 id 字段的这两个 AlterField 操作,因此迁移只是您实际想要进行的更改并应用它。然后为 id 更改创建一个单独的迁移并运行 python manage.py migrate intake --fake 以将新迁移标记为已应用但不实际运行它。

标签: python django django-models django-migrations


【解决方案1】:

在 ID 为 BigAutoFieldmakemigrations 之后,我的项目遇到了完全相同的问题。事实证明,这个 SQL 错误是由以前的问题引起的。 如果您运行./manage.py showmigrations,它应该提到您的 0021 摄入迁移尚未完成。

intake
 [X] 0001_initial
 [X] 0002_auto_20220214_1030
 [X] ...
 [ ] intake.0021_auto_20220115_1147

但是,您的数据库中的django_migrations 表应列出此intake.0021 迁移。这意味着它已经被应用了。

SELECT name FROM django_migrations WHERE app = 'intake' AND starts_with(name, '0021');

但是,列出的 DB 名称可能与现有文件名略有不同:0021_auto_20220115_1147(运行@ 11:47)。例如在 DB 中:0021_auto_20220115_1056(运行@10:56)。这可能是由于 makemigrations 在与当前使用的服务器 (dev) 不同的服务器上完成的。

根据您在数据库中django_migrations 中的内容更改文件名并再次运行manage.py migrate,它应该可以工作。

错误是由 ALTER SEQUENCE 语句引起的。

ALTER SEQUENCE "intake_byattorney_id_seq" OWNED BY "intake_byattorney"."id";
ALTER SEQUENCE "intake_client_id_seq" OWNED BY "intake_client"."id";

使用 postgres,AutoField 主键由序列管理。为什么 django 不使用 ALTER SEQUENCE seq_name as bigint 语法而不是 DROP - CREATE?我不知道,但manage.py 完成的CREATE SEQUENCEpostgres OWNER 分配给序列,这就是问题的根源,因为与序列关联的 table.column dbuser所有者

因此,ALTER SEQUENCE OWNED BY 语句的执行愿意将新创建的序列关联到具有不同 OWNER 的适当 table.column 将触发 sequence must have same owner as table it is linked to 错误。

【讨论】:

    猜你喜欢
    • 2021-07-12
    • 2017-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-04
    • 1970-01-01
    • 2017-03-15
    • 1970-01-01
    相关资源
    最近更新 更多