如何实现在Django多值属性?(How to implement multivalued attr

2019-09-28 15:13发布

我有以下表格旧的数据库:

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

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

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

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的预计的电话号码的表有一个代理键。 由于电话号码的表是不是一个实体,它并没有在我的旧的数据库代理键。 注意,PHONENUMBERS'表主键是它的所有列的组合物。

我怎样才能在这些表到Django的模型映射,使之与我的遗产数据库中运行?

Answer 1:

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

请注意,我在人改名主键字段。 这仅仅是一个表面上的变化。 这是因为该公约是有主键字段的ID。 当你在处理大量的模型,你可能会忘记,这款机型的主键被命名不同。 因此变化。



Answer 2:

在Django中,所有的车型(为你写的或inspectdb生成) 必须卡瓦主键 。

如果你喜欢用表PHONENUMBERS像模特,你将需要这个表有一个主键。

在这种情况下,我的建议是你修改你的遗留表手动添加一个新的主键,并丢弃您的复合主键。 旧版表有一个复合主键(PHONE_NUMBER + AREA_CODE),这是不是在Django官方支持。



文章来源: How to implement multivalued attribute in Django?