1

我有一个包含以下表格的旧数据库:

person_id (PK)  |  first_name  |  last_name
        1       |  John        |  Doe
        2       |  David       |  Bentley

电话号码

person_id (FK,PK) |  phone_number (PK)  | area_code (PK)
        1         |  758-4551           | 909
        1         |  763-3445           | 909
        2         |  634-0011           | 637

每个人都可以有零个或多个电话号码,这是个人实体的多值属性。

我尝试使用 Django 的 inspectdb 命令生成以下 models.py:

class Person(models.Model):
    person_id = models.BigIntegerField(primary_key=True)
    first_name = models.CharField(max_length=255)
    last_name = models.CharField(max_length=255)

    class Meta:
        managed = False
        db_table = 'person'


class PhoneNumbers(models.Model):
    person = models.ForeignKey(Person, models.DO_NOTHING)
    phone_number = models.CharField(max_length=15)
    area_code = models.CharField(max_length=15)

    class Meta:
        managed = False
        db_table = 'phonenumbers'
        unique_together = (('person', 'phone_number', 'area_code'),)

但是,当我尝试保存 PhoneNumbers 的新实例时,Django 返回以下错误消息:

django.db.utils.ProgrammingError: column phonenumbers.id does not exist

显然 Django 期望电话号码的表有一个代理键。由于电话号码表不是实体,因此它在我的旧数据库中没有代理键。请注意,电话号码表的主键是其所有列的组合。

如何将这些表映射到 Django 的模型中,以便它与我的旧数据库一起使用?

4

2 回答 2

1

在 Django 中,所有模型(为您编写或使用 inspectdb 生成)都必须保留 Primary Key

如果您喜欢像模型一样使用表电话号码,则需要该表具有主键。

在这种情况下,我的建议是修改旧表以手动添加新主键并丢弃复合主键。您的旧表有一个复合主键(phone_number + area_code),这在 Django 中不受正式支持。

于 2016-06-08T20:13:12.597 回答
0

Django 不支持复合主键,您的 PhoneNumbers 表有一个跨越三列的主键。这张已经开很多年了。有一个提供复合主键支持的第三方插件,但它已经两年未维护并且与最新版本的 Django 不兼容。

解决方案是添加主键。但在那之前做

./manage.py migrate

这将确保 django 所需的表是在您的旧数据库中创建的。

现在修改您的模型以删除此行

managed = False

这向 django 发出信号,表明模型的更改将反映在数据库中。然后按如下方式更改您的模型。

class Person(models.Model):
    id = models.BigIntegerField(primary_key=True, db_column='person_id')
    first_name = models.CharField(max_length=255)
    last_name = models.CharField(max_length=255)

    class Meta:
        db_table = 'person'


class PhoneNumbers(models.Model):
    id = models.BigIntegerField(primary_key=True)
    person = models.ForeignKey(Person, models.DO_NOTHING)
    phone_number = models.CharField(max_length=15)
    area_code = models.CharField(max_length=15)

    class Meta:
        db_table = 'phonenumbers'
        unique_together = (('person', 'phone_number', 'area_code'),)

然后做

 ./manage.py makemigrations  your_app_name
 ./manage.py migrate

请注意,我已重命名 Person 中的主键字段。这只是表面上的改变。这是因为约定是将主键字段作为 id。当您处理大量模型时,您可能会忘记该模型的主键名称不同。因此发生了变化。

于 2016-06-09T04:04:43.810 回答