【问题标题】:Django migrations - Get current app name in RunPython functionDjango 迁移 - 在 RunPython 函数中获取当前应用程序名称
【发布时间】:2019-08-27 01:10:24
【问题描述】:

我的一个迁移具有使用RunPython 运行的附加功能。此消息的目的只是向用户显示一个快乐的消息。唯一的问题是,我需要显示一个应用程序名称,当前迁移是在其中创建和运行的。这有点可能吗?

我的代码

from django.db import migrations, models
import django.db.models.deletion


def happy_message(apps, schema_editor):
    print('A happy message from migration inside app named {}')


class Migration(migrations.Migration):

    operations = [
        migrations.AddField(
            model_name='mymodel',
            name='rank_no',
            field=models.IntegerField(null=True),
        ),
        migrations.RunPython(
            happy_message,
            migrations.RunPython.noop
        ),
    ]

【问题讨论】:

  • 您可以使用--name 标志选项命名您正在迁移

标签: django django-migrations


【解决方案1】:

如果你使用的是经典的 Django 文件架构,那么你的迁移文件应该位于project_dir/app_dir/migrations/0001_migration_file.py

然后,就可以简单的获取应用目录名了:

from os.path import basename, dirname

def happy_message(apps, schema_editor):
    app_name = basename(dirname(dirname(__file__)))
    print(f'A happy message from migration inside app named {app_name}')

【讨论】:

  • 那行得通。但是,它似乎有点 hacky。
  • 是的,但我还没有找到从 RunPython 的迁移对象中检索“app_label”属性的方法^^
【解决方案2】:

您可以对自定义RunPythoncode(和reverse_code)属性进行猴子修补,以支持额外的参数app_label

from django.db import migrations


class AppAwareRunPython(migrations.RunPython):

    # MonkeyPatch the `code` call with a lambda that add an extra argument `app_label`
    def database_forwards(self, app_label, schema_editor, from_state, to_state):
        mp_code = self.code
        self.code = lambda apps, se: mp_code(apps, se, app_label)
        super().database_forwards(app_label, schema_editor, from_state, to_state)

    # Same for backwards if you want to display message when unapplying the migration
    def database_backwards(self, app_label, schema_editor, from_state, to_state):
        if self.reverse_code:
            mp_reverse_code = self.reverse_code
            self.reverse_code = lambda apps, se: mp_reverse_code(apps, se, app_label)
        super().database_backwards(app_label, schema_editor, from_state, to_state)

    # Add the etra argument to noop
    @staticmethod
    def noop(apps, schema_editor, app_label=None):
        migrations.RunPython.noop(apps, schema_editor)


# This function can't be used with classic RunPython unless you put `app_label=None` and test its value
def happy_message(apps, schema_editor, app_label):
    print(f'A happy message from migration inside app named {app_label}')


class Migration(migrations.Migration):

    operations = [
        AppAwareRunPython(happy_message, AppAwareRunPython.noop),
    ]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-15
    • 2010-11-24
    • 2015-10-07
    • 2013-06-25
    • 2015-04-10
    • 2015-02-02
    相关资源
    最近更新 更多