Alb*_*lla 10 migration django manytomanyfield django-1.7 django-migrations
我正在尝试向我之前创建的ManyToMany字段添加订单.我基本上想订购图片集中的图片.我在Django 1.7上运行,所以没有更多的南迁移(我试图遵循这个教程:http://mounirmesselmeni.github.io/2013/07/28/migrate-django-manytomany-field-to-manytomany-through -with -南/)
这是我的"通过"关系:
class CollectionPictures(models.Model):
picture = models.ForeignKey(
Picture,
verbose_name=u'Picture',
help_text=u'Picture is included in this collection.',
)
collection = models.ForeignKey(
Collection,
verbose_name=u'Collection',
help_text=u'Picture is included in this collection',
)
order = models.IntegerField(
verbose_name=u'Order',
help_text=u'What order to display this picture within the collection.',
max_length=255
)
class Meta:
verbose_name = u"Collection Picture"
verbose_name_plural = u"Collection Pictures"
ordering = ['order', ]
def __unicode__(self):
return self.picture.name + " is displayed in " + self.collection.name + (
" in position %d" % self.order)
class Collection(models.Model):
pictures = models.ManyToManyField(Picture, through='CollectionPictures', null=True)
[... Bunch of irrelevant stuff after]
Run Code Online (Sandbox Code Playgroud)
因此,如果我不必迁移旧数据,这应该有效(模型中唯一的区别是它没有 通过='CollectionPictures'
这是我的迁移:
class Migration(migrations.Migration):
dependencies = [
('artist', '0002_auto_20141013_1451'),
('business', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='CollectionPictures',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('order', models.IntegerField(help_text='What order to display this picture within the collection.', max_length=255, verbose_name='Order')),
('collection', models.ForeignKey(verbose_name='Collection', to='business.Collection', help_text='Picture is included in this collection')),
('picture', models.ForeignKey(verbose_name='Picture', to='artist.Picture', help_text='Picture is included in this collection.')),
],
options={
'ordering': ['order'],
'verbose_name': 'Collection Picture',
'verbose_name_plural': 'Collection Pictures',
},
bases=(models.Model,),
),
migrations.AlterField(
model_name='collection',
name='pictures',
field=models.ManyToManyField(to=b'artist.Picture', null=True, through='business.CollectionPictures'),
),
]
Run Code Online (Sandbox Code Playgroud)
这在迁移时会引发错误:
ValueError:无法将字段business.Collection.pictures更改为business.Collection.pictures - 它们不是兼容类型(您无法更改到M2M字段或从M2M字段更改,或在M2M字段上添加或删除)
有没有人已经尝试过这种新的1.7迁移操作?
谢谢 !
Kev*_*nry 22
最安全的方法是创建一个新字段并复制数据.
pictures单独留下并添加pictures2你的through字段.跑makemigrations.
编辑生成的迁移文件,并添加一个RunPython命令,将数据从旧表复制到新表.也许您可以以编程方式为新order列选择一个好的值.
删除旧pictures字段.跑makemgirations.
重命名pictures2为pictures.跑makemigrations.
这种方法应该使您处于所需的状态,并保持数据的完整性.
如果复制数据是一个大问题,你可以尝试别的东西,比如order在SQL中添加列,使用db_table选项on CollectionPictures使其指向现有表,然后擦除迁移和重做--fake.但这似乎比上述方法更具风险.
老问题,但我也遇到了这个问题,我找到了一种适用于 Django 1.11 的方法,并且也应该适用于旧版本。所需的类存在回到 1.7 并且仍然存在于 2.0
修复涉及使用SeparateDatabaseAndState迁移类手动更改迁移以执行我们想要的操作。这个类让 Django 更新状态,但让我们控制要执行的操作。在这种情况下,我们只想重命名模型表,其他一切都已经设置好了。
步骤:
创建新的 ManyToMany Through 模型,但指定自定义表名,并且没有额外的字段:
class CollectionPictures(models.Model):
collection = ...
picture = ...
class Meta:
# Change myapp to match.
db_table = "myapp_collection_pictures"
unique_together = (("collection", "picture"))
Run Code Online (Sandbox Code Playgroud)采用现有的迁移,并采用它生成的操作并将其全部包装在一个 new 中SeparateDatabaseAndState:
class Migration(migrations.Migration):
dependencies = [
('artist', '0002_auto_20141013_1451'),
('business', '0001_initial'),
]
operations = [
migrations.SeparateDatabaseAndState(
database_operations=[
],
state_operations=[
migrations.CreateModel(
name='CollectionPictures',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('order', models.IntegerField(help_text='What order to display this picture within the collection.', max_length=255, verbose_name='Order')),
('collection', models.ForeignKey(verbose_name='Collection', to='business.Collection', help_text='Picture is included in this collection')),
('picture', models.ForeignKey(verbose_name='Picture', to='artist.Picture', help_text='Picture is included in this collection.')),
],
options={
'ordering': ['order'],
'verbose_name': 'Collection Picture',
'verbose_name_plural': 'Collection Pictures',
},
bases=(models.Model,),
),
migrations.AlterField(
model_name='collection',
name='pictures',
field=models.ManyToManyField(to=b'artist.Picture', null=True, through='business.CollectionPictures'),
),
]
)
Run Code Online (Sandbox Code Playgroud)db_table从类 Meta 中删除,并在SeparateDatabaseAndState,之后添加此操作(而不是进入 database_operations。):
migrations.AlterModelTable(
name='collectionpicture',
table=None,
),
Run Code Online (Sandbox Code Playgroud)现在,如果你运行`./mange.py sqlmigrate myapp 0003(选择正确的数字前缀!)你应该幸运地看到这样的输出:
class CollectionPictures(models.Model):
collection = ...
picture = ...
class Meta:
# Change myapp to match.
db_table = "myapp_collection_pictures"
unique_together = (("collection", "picture"))
Run Code Online (Sandbox Code Playgroud)
(如果您乐于将自定义表名保留在那里,则不严格要求第 3 步。)
并仔细检查./manage.py makemigrations --check- 它应该打印“未检测到更改”。
| 归档时间: |
|
| 查看次数: |
5593 次 |
| 最近记录: |