0

I am changing the primary key of the legacy database. I was able to change the primary key by setting id as the primary key.

Before

class User(models.Model):
    name = models.CharField(max_length=5)
    email = models.CharField(max_length=5)
    age = models.CharField(max_length=5)

After

class User(models.Model):
    id = models.BigIntegerField(primary_key=True)
    name = models.CharField(max_length=5)
    email = models.CharField(max_length=5)
    age = models.CharField(max_length=5)

Then

python manage.py makemigrations
python manage.py migrate

This is working fine. But I also want to change the default primary key of the tables created via ManyToMany feild.

User Model

class User(models.Model):
    id = models.BigIntegerField(primary_key=True)
    name = models.CharField(max_length=5)
    email = models.CharField(max_length=5)
    age = models.CharField(max_length=5)

UserProfile Model

class UserProfile(models.Model):
    id = models.BigIntegerField(primary_key=True)
    address = models.CharField(max_length=5)
    father_name = models.CharField(max_length=5)
    pincode = models.CharField(max_length=5)
    user = models.ManyToManyField(User)

The ManytoMany field creates table called User_user_userprofile with id as Autofield basically previous or default django primary key.

id, user_id, userprofile_id ManytoMany Table

Now, How to change the primarykey of ManytoMany Feild ie id created by Django?

PS: Django: 1.11 Python: 2.7.5 DB: Sqlite3 3.7.17 2013-05-20

1 Answers1

1

I stumbled upon this problem today, and ended up solving it by using the through argument of the ManyToManyField. I solved it for Django v3.2.6 however, but the documentation for v1.11 mentions the same behavior for the same argument, so hopefully the solution should work for your version of Django too. Here's the link to the documentation for v1.11 ManyToManyField.through

What the through argument allows you to do is to create the intermediary table (created automatically by ManyToManyField) yourself. You get finer control of how the intermediary table should look like, what fields it should have and what their behavior should be. Hope you are getting a picture.

Let me give you the example of the problem I faced and how I solved it. Hopefully that will make this clearer.

I was trying to establish a many-to-many relationship between two of my existing models.

My first model looks like this,

class BanglaWords(models.Model):
    class Meta:
        verbose_name_plural = 'Bangla Words'

    bng_id = models.CharField(max_length=16, primary_key=True)
    bangla_word = models.CharField(max_length=64)

    def __str__(self):
        return self.bangla_word

and the second one looks like,

class EnglishWords(models.Model):
    class Meta:
        verbose_name_plural = 'English Words'

    eng_id = models.IntegerField(primary_key=True)
    word = models.CharField(max_length=64)
    bangla_word = models.ManyToManyField(BanglaWords)

    def __str__(self):
        return self.word

But this resulted in an intermediary table wordnet_englishwords_bangla_word which looked like this,

wordnet_englishwords_bangla_word
id
englishwords_id
banglawords_id

But I didn't want this, I wanted bng_id to be the pk for this table. I solved the problem with ManyToManyField.through as follows,

I defined the intermediary model(table) myself and with the through argument, I pointed to the new intermediary model I created and instructed django to create the table the way I wanted it.

First I created the intermediary model,

class BanglaEnglishRelations(models.Model):
    class Meta:
        verbose_name_plural = 'Bangla English Relations'

    bng_id = models.OneToOneField('BanglaWords', primary_key=True, on_delete=models.CASCADE)
    eng_id = models.ForeignKey('EnglishWords', on_delete=models.CASCADE)

which defines bng_id as the primary key as I desired.

Second, I told the ManyToManyField in EnglishWords to base the table on BanglaEnglishRelations like,

bangla_word = models.ManyToManyField(BanglaWords, through=BanglaEnglishRelations)

This resulted in the table wordnet_banglaenglishrelations which looked like,

wordnet_banglaenglishrelations
bng_id_id
eng_id_id

and surved my purposes. You can do something similar to solve your problem and promote whatever field to a pk.

Shaphil
  • 13
  • 1
  • 6