如何在使用ManyToMany字段的'through'时使用south迁移?
我想在一个Django应用中修改一个多对多的字段。
我有以下这些模型:
class A:
...
class B:
as = models.ManyToManyField(A)
我想要的是:
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)
我在使用south来进行数据库迁移。不幸的是,在这种情况下,south建议删除现有的 app_b_a
表,然后重新创建一个新的 app_c
。
有没有办法告诉south不要重新创建这个多对多的表?
3 个回答
0
你也可以试着把C的db_table参数设定为'app_b_a'。不过我不确定这样做是否有效。
2
我最近也遇到过这个问题,其实挺简单的。
首先,先在你的代码里添加一个新的中间模型,但不要把它指定为ManyToManyField
的through
参数。接下来,创建一个自动的模式迁移,这样就会为你生成一个新的表。
$ python manage.py schemamigration --auto yourapp
第二步,创建一个数据迁移:
$ python manage.py datamigration yourapp name_of_migration
在你的前向迁移中:
for b in orm.B.objects.all():
for a in b.as.all():
orm.C.objects.create(a=a, b=b)
在你的后向迁移中:
for c in orm.C.objects.all():
c.b.as.add(a)
最后,把through
参数添加到你的ManyToManyField
里,然后再生成一个自动的模式迁移:
$ python manage.py schemamigration --auto yourapp
6
我会这样做:
- 先添加一个
C
模型,但不要添加任何额外的数据字段。只需要把两个外键(FK)设置为关联的模型,这样它的结构就和默认的多对多(m2m)表几乎一样,只是表名不同。 - 为你的应用运行
schemamigration --auto
。 - 为了有效地“删除”现有的表并“创建”一个新的表,而不移动数据,只需删除
forwards
和backwards
方法中生成的所有迁移代码,然后添加: forwards:db.rename_table('yourappname_m2mtablename', 'yourappname_c')
backwards:db.rename_table('yourappname_c', 'yourappname_m2mtablename')
- 保持“冻结”的模型字典不变!
- 现在你可以扩展你的
C
模型,并为它生成一个新的迁移。