Django inspectdb 不尊重两列上的主键(postgres)
Django inspectdb not respecting primary key on two columns (postgres)
我正在使用 Django 连接到现有的 Postgres 数据库,使用 inspectdb 生成我的 models.py 文件。
Postgres 中的 tables 是这样创建的:
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。
如果我改为创建 table 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
上。我怀疑这是一个错误,但我没有经验所以想在报告之前在这里问一下。
第二个问题:如果这是一个错误,是否值得报告?也许数据库设计很差或不常见?
I suspect this is a bug, but I am inexperienced so wanted to ask here before reporting.
不是真的。 Django 不适用于跨越两列或更多列的主键,或者至少在撰写本文时如此。它已被请求,例如 ticket #373,但设计者决定将其设置为 "wontfix"。
documentation进一步解释了这一点:
Do Django models support multiple-column primary keys?
No. Only single-column primary keys are supported.
But this isn’t an issue in practice, because there’s nothing stopping
you from adding other constraints (using the unique_together
model
option or creating the constraint directly in your database), and
enforcing the uniqueness at that level. Single-column primary keys are
needed for things such as the admin interface to work; e.g., you need
a single value to specify an object to edit or delete.
您可能在(不久的)将来无法做到这一点,因为很多 Django 工具都是在假设主键是 "scalar" 个实体的情况下构建的。
因此您可能应该稍微重新设计现有的数据库,然后尝试 运行 inspectdb
。
我正在使用 Django 连接到现有的 Postgres 数据库,使用 inspectdb 生成我的 models.py 文件。 Postgres 中的 tables 是这样创建的:
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。
如果我改为创建 table 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
上。我怀疑这是一个错误,但我没有经验所以想在报告之前在这里问一下。
第二个问题:如果这是一个错误,是否值得报告?也许数据库设计很差或不常见?
I suspect this is a bug, but I am inexperienced so wanted to ask here before reporting.
不是真的。 Django 不适用于跨越两列或更多列的主键,或者至少在撰写本文时如此。它已被请求,例如 ticket #373,但设计者决定将其设置为 "wontfix"。
documentation进一步解释了这一点:
Do Django models support multiple-column primary keys?
No. Only single-column primary keys are supported.
But this isn’t an issue in practice, because there’s nothing stopping you from adding other constraints (using the
unique_together
model option or creating the constraint directly in your database), and enforcing the uniqueness at that level. Single-column primary keys are needed for things such as the admin interface to work; e.g., you need a single value to specify an object to edit or delete.
您可能在(不久的)将来无法做到这一点,因为很多 Django 工具都是在假设主键是 "scalar" 个实体的情况下构建的。
因此您可能应该稍微重新设计现有的数据库,然后尝试 运行 inspectdb
。