我有一个自定义图像和演绎模型,并遵循the wagtail v2.4 guide来实现它们:
class AccreditedImage(AbstractImage):
"""
AccreditedImage - Customised image model with optional caption and accreditation
"""
caption = models.CharField(max_length=255, blank=True)
accreditation = models.CharField(max_length=255, blank=True, null=True)
admin_form_fields = Image.admin_form_fields + (
'caption',
'accreditation',
)
class Meta:
verbose_name = 'Accredited image'
verbose_name_plural = 'Accredited images'
def __str__(self):
credit = ' ({})'.format(self.accreditation) if (self.accreditation is not None) and (len(self.accreditation) > 0) else ''
return '{}{}'.format(self.title, credit)
class AccreditedRendition(AbstractRendition):
"""
AccreditedRendition - stores renditions for the AccreditedImage model
"""
image = models.ForeignKey(AccreditedImage, on_delete=models.CASCADE, related_name='renditions')
class Meta:
unique_together = (('image', 'filter_spec', 'focal_point_key'),)
verbose_name = 'Accredited Image Rendition'
verbose_name_plural = 'Accredited Image Renditions'
在settings
我有:
WAGTAILIMAGES_IMAGE_MODEL = 'cms.AccreditedImage'
但是,我安装了两个第三方插件:puput和wagtail_events,每个插件使用外键来扭曲图像。
当我运行`manage.py makemigrations时,会在puput和wagtail_events site_packages文件夹中创建其他迁移以处理FK中的更改。迁移看起来像这样:
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('puput', '0005_blogpage_main_color'),
]
operations = [
migrations.AlterField(
model_name='blogpage',
name='header_image',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='cms.AccreditedImage', verbose_name='Header image'),
),
migrations.AlterField(
model_name='entrypage',
name='header_image',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='cms.AccreditedImage', verbose_name='Header image'),
),
]
如果我实际应用这些迁移,那么puput或wagtail_events会发布新版本,然后迁移历史记录会被破坏 - 例如我自动生成的0006 *迁移在puput和他们的新0006 *迁移分叉历史
有没有办法克服这个?或者推荐做什么做法?
此时我处于测试阶段,所以我可以转储整个数据库并重新启动,如果建议的策略是从一开始就设置它以避免问题。
伙计们,感谢您的帮助!
第三方库中的初始迁移应定义可交换的依赖项,例如:from wagtail.images import get_image_model_string
dependencies = [
migrations.swappable_dependency(get_image_model_string()),
]
operations = [
migrations.CreateModel(
name='ThirdPartyModel',
fields=[
...
('image', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, to=get_image_model_string())),
],
...
),
这不是由makemigrations自动创建的。 get_image_model_string
需要在每个影响FK的迁移中使用,这是通过库的整个迁移历史记录完成的。
如果您在项目中的某个位置更改设置,您仍然需要进行数据迁移('Migrate an existing swappable dependency'可能有帮助),但如果开始清理,这将解决上述分叉问题。
它的缺点是需要控制第三方库。我没有屏住呼吸像puput
这样的项目回去改变他们早期的迁移历史,以允许一个可交换的图像模型(puput的初始迁移硬编码wagtailimages.Image
)。但我已经为wagtail_events
(我自己的项目)实现了这个,以拯救其他人这个麻烦。
啊。我一直在研究这个问题,所有候选解决方案都非常可怕。我考虑让我的自定义图像类通过db_table元属性模拟wagtail.images.model.Image
,甚至创建另一个基本上复制wagtail图像的应用程序。这要么是大量的工作要么是超级黑客。
我选择使用MIGRATION_MODULES
设置手动接管迁移。
对于我的场景,我已经获取了puput的整个迁移历史记录,并将所有文件复制到一个单独的文件夹root/custom_puput_migrations/
中。我设置
MIGRATION_MODULES = {
'puput': 'custom_puput_migrations'
}
WAGTAILIMAGES_IMAGE_MODEL = 'otherapp.AccreditedImage'
然后我通过在该文件夹中编辑0001_initial.py
来拉动'switcharoo'以通过设置引用模型,而不是通过硬编码:
...
from wagtail.images import get_image_model_string
class Migration(migrations.Migration):
dependencies = [
...
migrations.swappable_dependency(get_image_model_string())
]
operations = [
migrations.CreateModel(
name='BlogPage',
fields=[
...
('header_image', models.ForeignKey(related_name='+', on_delete=django.db.models.deletion.SET_NULL, verbose_name='Header image', blank=True, to=get_image_model_string(), null=True)),
],
...
1)创建的实际表关系不是由迁移文件严格确定的,而是由设置决定的,该设置可以独立更改。如果您希望避免这种情况,则可以在自定义迁移中简单地对引用的模型进行硬编码。
2)这种方法使您很容易受到开发人员升级库版本要求的影响,而不会意识到他们还必须手动复制迁移文件。我建议在允许应用程序启动之前检查(f / ex确保默认迁移文件夹中的文件数与自定义文件中的文件数相同),以确保您的开发和生产数据库都在同一组迁移。