How to implement multivalued attribute in Django?

匆匆过客 提交于 2019-12-11 05:26:18

问题


I have a legacy database with the following tables:

person

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

phonenumbers

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

Every person can have zero or more phone numbers, which is a multivalued attribute of the person entity.

I've tried using the Django's inspectdb command which generated the following 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'),)

However, when I tried to save a new instance of PhoneNumbers, Django returned the following error message:

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

Apparently Django expects the phone number's table to have a surrogate key. Since the phone number's table is not an entity, it doesn't have a surrogate key in my legacy database. Notice that the phonenumbers' table primary key is a composition of all of its columns.

How can I map these tables into Django's models so that it works with my legacy database?


回答1:


Django does not support composite primary keys and your PhoneNumbers table has a primary key that spans three columns. This ticket has been open for years. There is a third party plugin that provide composite primary key support but it's been unmaintained for two years and incompatible with the latest versions of Django.

The solution is to add the primary key. But before that do

./manage.py migrate

This will make sure that the tables needed by django are created in your legacy database.

Now modify your models to delete this line

managed = False

This signals django that alterations to the models are to be reflected in the database. Then change your model as follows.

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'),)

Then do

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

Notice that I have renamed the primary key field in Person. This is just a cosmetic change. That's because the convention is to have the primary key field as id. When you are dealing with lots of models you are likely to forget that this model's primary key was named differently. Hence the change.




回答2:


In Django, all the Models (written for you or generated with inspectdb) must kave Primary Key.

If you like to use the table phonenumbers like a Model, you will need that this table have a primary key.

In this scenario, my advice is that you modify your legacy table to add a new primary key manually and discard your composite primary key. Your legacy table have a composite primary key (phone_number+area_code) and this is not supported officially in Django.



来源:https://stackoverflow.com/questions/37711512/how-to-implement-multivalued-attribute-in-django

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!