似乎这应该是“容易的”或者至少在某处记录,我只是无法找到它。
假设我有一个模特:
class A(models.Model):
users = models.ManyToMany('auth.User', blank=True)
现在我想迁移到一个through
表来向ManyToMany关系添加字段......
class AUsers(models.Model):
user = models.ForeignKey('auth.User')
a = models.ForeignKey('A')
new_field = models.BooleanField()
class A(models.Model):
users = models.ManyToMany('auth.User', blank=True, through='AUsers')
然后我这样做:
% ./manage.py schemamigration app --auto
并不完全令人惊讶,它告诉我它将删除原始自动创建的表并为AUsers
创建一个新的。目前最好的做法是什么?是否有适当的方法迁移到新的through
表?我在Meta中使用db_table
吗?我是不是马上使用through=...
...然后执行schemamigration --auto
,然后执行datamigration
复制当前表(不知何故,不确定...)然后添加through
关系,让它杀死桌子?
这里的诀窍是什么?这真的很难吗?
答案 0 :(得分:14)
你应该可以很容易地做到这一点。
首先,确保您创建的手动表在数据库中具有与Django最初自动创建的表名相同的表名。
因此,首先,让我们在您做出改变之前考虑手动通过模型:
class AUsers(models.Model):
user = models.ForeignKey('auth.User')
a = models.ForeignKey('A')
class Meta:
db_table = 'appname_a_user'
这应该在功能上(几乎)与您曾经拥有的ManyToManyField
相同。实际上,你可以进行空迁移并应用它,然后使用--auto进行更改(但不要)。
现在,像上面的示例代码中一样添加字段,然后运行./manage.py schemamigration appname manual_through_table --empty
。这将为您提供名为####_manual_through_table.py
的空迁移。
在迁移本身中,会有forwards
和backwards
方法。每个人都需要一行:
def forwards(self, orm):
db.add_column('appname_a_user', 'new_field', self.gf('django.db.models.fields.BooleanField')(default=False))
def backwards(self, orm):
db.delete_column('appname_a_user', 'new_field')
那应该能让你得到你想要的东西。
答案 1 :(得分:5)
如果有人在尝试使用现代迁移框架执行相同操作时遇到此问题,请执行以下步骤:
migrations. SeparateDatabaseAndState
迁移中,其中自动生成的步骤位于state_operations
字段中,并且数据库操作为空。答案 2 :(得分:0)
正如评论中所提到的,可以使用db.rename_table
简化第一步,如here所述,通过模型提供此内容:
class AUsers(models.Model):
user = models.ForeignKey('auth.User')
a = models.ForeignKey('A')
class Meta:
unique_together = (('user', 'a'),)
然后,使用--auto创建迁移(这样您就可以看到数据库表的名称),并将内容替换为:
class Migration(SchemaMigration):
def forwards(self, orm):
db.rename_table('appname_a_user', 'appname_auser')
def backwards(self, orm):
db.rename_table('appname_auser','appname_a_user')
我刚刚在我的项目中应用它而没有任何问题。