I want to change a ManyToMany field in a django app.
I have the following models:
class A:
...
class B:
as = models.ManyToManyField(A)
and I want:
class A:
...
class C:
a = models.ForeignKey(A)
b = models.ForeignKey("B")
extra_data = models.BooleanField(default=False)
class B:
as = models.ManyToManyField(A, through=C)
I am using south for db migrations. Unfortunately, in this case, south propse to delete the existing app_b_a
table and to recreate a new app_c
.
Is there a way to say to south not to recreate the m2m table?
I would try to do it the following way:
C
model but do not add any extra data fields to it yet. Just set the 2 FK's to the linked models, so that it's schema is effectively identical to the default m2m table, except table name.schemamigration --auto
for your app.forwards
/backwards
methods and add:
forwards: db.rename_table('yourappname_m2mtablename', 'yourappname_c')
backwards: db.rename_table('yourappname_c', 'yourappname_m2mtablename')
C
model and generate a new schemamigration for it.Just had to do this myself recently. It's actually fairly easy.
First, add the new through model to your code, but don't specify it as the through
parameter to your ManyToManyField
yet. Create an auto schemamigration, which will create the new table for you.
$ python manage.py schemamigration --auto yourapp
Second, create a datamigration:
$ python manage.py datamigration yourapp name_of_migration
In your forwards migration:
for b in orm.B.objects.all():
for a in b.as.all():
orm.C.objects.create(a=a, b=b)
In your backwards migration:
for c in orm.C.objects.all():
c.b.as.add(a)
Finally, add the through
parameter to your ManyToManyField
, and generate another auto schemamigration:
$ python manage.py schemamigration --auto yourapp
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