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...
This is nontrivial, I think you will need three migrations:
ForeignKey
.ManyToMany
to ForeignKey
(using the forwards
method).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:
backwards
method here yet.You will also need to update the code that uses those relationships in step 2. / 3.
Based on the excellent answer provided by Thomas Orozco, I'd like to provide the solution for Django>=1.7 (basically the point 2 Convert the ManyToMany to ForeignKey is what varies in newer versions of Django). So here the code for the second migration:
class Migration(migrations.Migration):
def migrate_m2m_to_fk(apps, schema_editor):
Manufacturer = apps.get_model("app", "Manufacturer")
for manufacturer in Manufacturer.objects.all():
for car in manufacturer.car.all():
car.manufacturer = manufacturer
car.save()
def migrate_fk_to_m2m(apps, schema_editor):
Car = apps.get_model("app", "Car")
for c in Car.objects.all():
if c.manufacturer:
c.manufacturer.car.add(c)
c.manufacturer.save()
operations = [
migrations.RunPython(migrate_m2m_to_fk, migrate_fk_to_m2m)
]
Where "app" is the Django app where the models live. Both forward and reverse migration code is shown (as Thomas mentions, running this migrations may incur in loss of data, if more than one relationship was present beforehand, so please take care).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With