0

我有一个 python2.7 django 项目(我知道,我在 20 世纪!)里面有一些模型。我需要覆盖 makemigrations,以便迁移文件名的形式为 0001.py、0002.py 等,而不是像 0001_initial.py、0002_model1.py 等,默认情况下会发生这种情况。

我已经研究了如何创建自定义 manage.py 命令,并且我能够覆盖 makemigrations 命令。目前我的自定义命令(python2.7)代码如下所示:

路径/to/project/app/management/commands/makemigrations.py

from django.core.management.commands.makemigrations import Command as CoreMakeMigrationsCommand

class Command(CoreMakeMigrationsCommand):
    def handle(self, *args, **options):
        super(Command, self).handle(*args, **options)

它目前无非是调用原始的 makemigrations。我需要能够修改如何autodetector.py(这是 makemigrations 流程的一部分)决定文件命名的行为。在这个文件中,有suggest_name如下所示的方法:

@classmethod
    def suggest_name(cls, ops):
        """
        Given a set of operations, suggest a name for the migration they might
        represent. Names are not guaranteed to be unique, but put some effort
        into the fallback name to avoid VCS conflicts if possible.
        """
        if len(ops) == 1:
            if isinstance(ops[0], operations.CreateModel):
                return ops[0].name_lower
            elif isinstance(ops[0], operations.DeleteModel):
                return "delete_%s" % ops[0].name_lower
            elif isinstance(ops[0], operations.AddField):
                return "%s_%s" % (ops[0].model_name_lower, ops[0].name_lower)
            elif isinstance(ops[0], operations.RemoveField):
                return "remove_%s_%s" % (ops[0].model_name_lower, ops[0].name_lower)
        elif ops:
            if all(isinstance(o, operations.CreateModel) for o in ops):
                return "_".join(sorted(o.name_lower for o in ops))
        return "auto_%s" % get_migration_name_timestamp()

上面是从这里调用的,在另一个方法的同一个文件中arrange_for_graph

            for i, migration in enumerate(migrations):
                if i == 0 and app_leaf:
                    migration.dependencies.append(app_leaf)
                if i == 0 and not app_leaf:
                    new_name = "0001_%s" % migration_name if migration_name else "0001_initial"
                else:
                    new_name = "%04i_%s" % (
                        next_number,
                        migration_name or self.suggest_name(migration.operations)[:100],
                    )

我是覆盖核心文件的新手,无法弄清楚如何从我的原始自定义命令文件中仅覆盖这部分,以便满足我的要求?

此外,请告知这将如何影响随后对 makemigrations 的调用,因为它们将依赖于新的迁移文件集(具有修改的名称)。

谢谢

4

2 回答 2

2

好的,这就是我的做法。

创建一个 makemigrations.py 文件(如用于覆盖 manage.py 命令的 django 文档中所示),在其中创建一个继承“django.core.management.commands.makemigrations.Command”的命令类并覆盖方法write_migration_files,如下所示:

from django.core.management.commands.makemigrations import Command as CoreMakeMigrationsCommand


class Command(CoreMakeMigrationsCommand):
    def write_migration_files(self, changes):
        for item in changes.values():
            print('Overriding default names of migrations supplied by django core')
            item[0].name = item[0].name.split('_')[0]
        super(Command, self).write_migration_files(changes)
于 2020-06-16T19:28:58.160 回答
1

除非您有数百次迁移,否则我认为最简单的方法如下:

  1. 根据需要逐一创建迁移,但名称由 Django 决定。

  2. 重命名迁移:

    • 重命名文件:0002_migration_name.py->0002.py等。

    • 重命名文件中的引用,例如,替换:

      dependencies = [
          ('appname', '0002_migration_name'),
      ]
      

      经过:

      dependencies = [
          ('appname', '0002'),
      ]
      
  3. 仅当任何迁移以及所有以前的迁移具有您想要的名称时才应用它。

于 2020-06-04T08:56:29.100 回答