如何使用自定义WAGTAILIMAGES_IMAGE_MODEL管理第三方应用迁移

问题描述 投票:1回答:1

情况

我有一个自定义图像和演绎模型,并遵循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'

但是,我安装了两个第三方插件:puputwagtail_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 *迁移分叉历史

问题

有没有办法克服这个?或者推荐做什么做法?

此时我处于测试阶段,所以我可以转储整个数据库并重新启动,如果建议的策略是从一开始就设置它以避免问题。

伙计们,感谢您的帮助!

wagtail django-migrations
1个回答
1
投票

Answer 1 - if you have control over your third party libraries

第三方库中的初始迁移应定义可交换的依赖项,例如: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(我自己的项目)实现了这个,以拯救其他人这个麻烦。

Answer 2 - if you don't have control

啊。我一直在研究这个问题,所有候选解决方案都非常可怕。我考虑让我的自定义图像类通过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)),
            ],
     ...

Drawbacks

1)创建的实际表关系不是由迁移文件严格确定的,而是由设置决定的,该设置可以独立更改。如果您希望避免这种情况,则可以在自定义迁移中简单地对引用的模型进行硬编码。

2)这种方法使您很容易受到开发人员升级库版本要求的影响,而不会意识到他们还必须手动复制迁移文件。我建议在允许应用程序启动之前检查(f / ex确保默认迁移文件夹中的文件数与自定义文件中的文件数相同),以确保您的开发和生产数据库都在同一组迁移。

© www.soinside.com 2019 - 2024. All rights reserved.