Django: convert ManyToManyField to ForeignKey

django, django-models, python

Solution

This is nontrivial, I think you will need three migrations:

- Add the `ForeignKey`.

- Convert the `ManyToMany` to `ForeignKey` (using the `forwards` method).

- Remove the `ManyToMany`.

You could possibly merge 1 and 2 or 2 and 3 together, but I wouldn't recommend it. Additionally, you should also implement a `backwards` method for 2.

An example for 2.'s `forwards` would be:

class Migration(SchemaMigration):
    def forwards(self, orm):
        for manufacturer in orm.Manufacturer.objects.all():
             for car in manufacturer.car.all():
                  car.manufacturer = manufacturer
                  car.save()

Please note that:

- There is no `backwards` method here yet.

- This needs to be tested extensively: a migration is something you should be extra careful about.

- In case a car has two manufacturers, the last one will be kept.

- This is very inefficient, we do a Query per car per manufacturer!

You will also need to update the code that uses those relationships in step 2. / 3.

Problem

Let's supposed I created two models: ``` class Car(models.Model): name = models.CharField(max_length=50) size = models.IntegerField() class Manufacturer(models.Model): name = models.CharField(max_length=50) country = models.CharField(max_length=50) car = models.ManyToManyField(Car) ``` I added entries to both models, then I realized that each Car was only related to a unique Manufacturer. So, I should convert my ManyToManyField to a ForeignKey: ``` class Car(models.Model): name = models.CharField(max_length=50) size = models.IntegerField() manufacturer = models.ForeignKey(Manufacturer) class Manufacturer(models.Model): name = models.CharField(max_length=50) country = models.CharField(max_length=50) ``` How can I do that without losing my entries? I tried to look in South documentation but I did not found this way of conversion...

Original source