1

我正在使用 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'

请注意在 上定义的 OneToOneField aid

如果我改为将表 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 现在是 on cid。我怀疑这是一个错误,但我没有经验,所以想在报告之前在这里问一下。第二个问题:如果这是一个错误,是否值得报告?也许数据库设计很差或不常见?

4

1 回答 1

0

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

并不真地。Django 不适用于跨越两列或更多列的主键,或者至少在撰写本文时不能。它已被请求,例如通过票 #373,但设计师决定将其设置为“wontfix”。

文档进一步解释了这一点:

Django 模型是否支持多列主键

不可以。仅支持单列主键。

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

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

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

于 2020-02-16T14:30:49.093 回答