【问题标题】:Django inspectdb not respecting primary key on two columns (postgres)Django inspectdb 不尊重两列的主键(postgres)
【发布时间】:2020-05-31 14:48:31
【问题描述】:

我正在使用 Django 连接到现有的 Postgres 数据库,使用 inspectdb 生成我的 models.py 文件。 Postgres 中的表是这样创建的:

CREATE TABLE "a"
(
  "id" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'::uuid,
  CONSTRAINT "PK.a" PRIMARY KEY ("id")
)
CREATE TABLE "c"
(
  "id" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'::uuid,
  CONSTRAINT "PK.c" PRIMARY KEY ("id")
)
CREATE TABLE "b"
(
  "aid" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'::uuid,
  "cid" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'::uuid,
 CONSTRAINT "PK.b" PRIMARY KEY ("aid","cid"),
 CONSTRAINT "FK_a" FOREIGN KEY ("aid")
      REFERENCES "a" ("id") MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE CASCADE,
 CONSTRAINT "FK_c" FOREIGN KEY ("cid")
      REFERENCES "c" ("id") MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE CASCADE
)

然后我运行 python manage.py inspectdb --database primary > models_test.py,这会产生以下 models_test.py

class A(models.Model):
    id = models.UUIDField(primary_key=True)

    class Meta:
        managed = False
        db_table = 'a'


class B(models.Model):
    aid = models.OneToOneField(A, models.DO_NOTHING, db_column='aid', primary_key=True)
    cid = models.ForeignKey('C', models.DO_NOTHING, db_column='cid')

    class Meta:
        managed = False
        db_table = 'b'
        unique_together = (('aid', 'cid'),)


class C(models.Model):
    id = models.UUIDField(primary_key=True)

    class Meta:
        managed = False
        db_table = 'c'

注意在 aid 上定义的 OneToOneField。

如果我改为将表 b 创建为:

CREATE TABLE "b"
(
  "aid" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'::uuid,
  "cid" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'::uuid,
 CONSTRAINT "PK.b" PRIMARY KEY ("cid","aid"),
 CONSTRAINT "FK_a" FOREIGN KEY ("aid")
      REFERENCES "a" ("id") MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE CASCADE,
 CONSTRAINT "FK_c" FOREIGN KEY ("cid")
      REFERENCES "c" ("id") MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE CASCADE
)

然后重新运行 inspectdb 我得到以下输出:

class A(models.Model):
    id = models.UUIDField(primary_key=True)

    class Meta:
        managed = False
        db_table = 'a'


class B(models.Model):
    aid = models.ForeignKey(A, models.DO_NOTHING, db_column='aid')
    cid = models.OneToOneField('C', models.DO_NOTHING, db_column='cid', primary_key=True)

    class Meta:
        managed = False
        db_table = 'b'
        unique_together = (('cid', 'aid'),)


class C(models.Model):
    id = models.UUIDField(primary_key=True)

    class Meta:
        managed = False
        db_table = 'c'

请注意,OneToOneField 现在位于 cid。我怀疑这是一个错误,但我没有经验,所以想在报告之前在这里问一下。 第二个问题:如果这是一个错误,是否值得报告?也许数据库设计很差或不常见?

【问题讨论】:

  • Django 无法处理由两列(或多列)组成的主键。

标签: django inspectdb


【解决方案1】:

我怀疑这是一个错误,但我没有经验,所以想在报告之前在这里问一下。

不是真的。 Django 不适用于跨越两列或更多列的主键,或者至少在撰写本文时不能。例如,ticket #373 已提出请求,但设计者决定将其设置为“wontfix”。

documentation 进一步解释了这一点:

Django 模型是否支持多列主键

否。仅支持单列主键。

但这在实践中不是问题,因为没有什么可以阻止 您可以添加其他约束(使用 unique_together 模型 选项或直接在数据库中创建约束),以及 在该级别强制执行唯一性。单列主键是 管理界面等工作所需的东西;例如,你需要 用于指定要编辑或删除的对象的单个值。

您可能在(不久的)将来无法做到这一点,因为许多 Django 工具都是在假设主键是“标量”实体的情况下构建的。

因此,您可能应该稍微重新设计现有数据库,然后尝试运行 inspectdb

【讨论】:

    猜你喜欢
    • 2021-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-08
    • 2011-12-31
    • 1970-01-01
    • 2010-09-19
    相关资源
    最近更新 更多