在Django中自动生成自定义迁移

在Django中自动生成自定义迁移

问题描述:

Django提供了一个非常好的功能,称为 makemigrations ,它将基于模型的更改创建迁移文件。我们正在开发一个模块,我们将要生成自定义迁移。

Django provides a really nice feature called makemigrations where it will create migration files based on the changes in models. We are developing a module where we will want to generate custom migrations.

我在Django文档中找不到有关创建自定义迁移的很多信息。关于可以产生迁移的各种 Operation 类的文档,但是关于创建可以产生自定义的 Operation 类的自定义

I haven't found much info about creating custom migrations in the Django docs. There is documentation on the various Operation classes that can yield migrations but there's nothing about creating custom Operation classes that can yield custom migrations.

用于生成新迁移的自动检测器模块似乎也没有为添加自定义 Operation 类: https://github.com/django/django/blob/master/django/db/migrations/autodetector.py#L160

The autodetector module for generating new migrations also doesn't seem to leave much room for adding custom Operation classes: https://github.com/django/django/blob/master/django/db/migrations/autodetector.py#L160

看来这是完全静态的。还有其他方法可以生成自定义迁移,也许是通过将现有类与自定义管理命令一起使用?

It seems this is completely static. Are there other ways to generate custom migrations, perhaps by using existing classes with a custom management command?

您可以创建自定义迁移类以连接到makemigrations类并添加自定义迁移内容,然后使用 runscript命令执行。下面是一个示例模块,其中文件名为custom_migrations.py,位于您的一个应用程序的脚本文件夹中:

You can create a custom class to hook into the makemigrations class and add your custom migrations stuff then execute using the "runscript" command. Below is a sample module where the file is named custom_migrations.py and located in a "scripts" folder off one of your apps:

from django.core.management.commands.makemigrations import Command
"""
To invoke this script use:
   manage.py runscript custom_migrations --script-args [app_label [app_label ...]] name=my_special_migration verbosity=1
"""    

class MyMigrationMaker(Command):
    '''
    Override the write method to add more stuff before finishing
    '''


    def write_migration_files(self, changes):
        print("Do some stuff to \"changes\" object here...")
        super().write_migration_files(changes)



def run(*args):
    nargs = []
    kwargs = {}
    # Preload some options with defaults and then can be overridden in the args parsing
    kwargs['empty'] = True
    kwargs['verbosity'] = 1
    kwargs['interactive'] = True
    kwargs['dry_run'] = False
    kwargs['merge'] = False
    kwargs['name'] = 'custom_migration'
    kwargs['check_changes'] = False
    for arg in args:
        kwarg = arg.split('=', 1)
        if len(kwarg) > 1:
            val = kwarg[1]
            if val == "True":
                arg_val = True
            elif val == "False":
                arg_val = False
            elif val.isdigits():
                arg_val = int(val)
            else:
                arg_val = val
            the_kwargs[kwarg[0]] = arg_val
        else:
            nargs.append(arg)
    MyMigrationMaker().handle(*nargs, **kwargs)