检测是否在migrate / makemigrations命令的上下文中运行代码

时间:2015-10-15 08:56:42

标签: python django django-migrations django-1.8

我有一个带有动态选择的模型,如果我能保证在django-admin.py migrate / makemigrations命令的情况下运行代码以防止它创建或警告,我想返回一个空的选择列表无用的选择改变。

代码:

from artist.models import Performance
from location.models import Location

def lazy_discover_foreign_id_choices():
    choices = []

    performances = Performance.objects.all()
    choices += {performance.id: str(performance) for performance in performances}.items()

    locations = Location.objects.all()
    choices += {location.id: str(location) for location in locations}.items()

    return choices
lazy_discover_foreign_id_choices = lazy(lazy_discover_foreign_id_choices, list)


class DiscoverEntry(Model):
    foreign_id = models.PositiveIntegerField('Foreign Reference', choices=lazy_discover_foreign_id_choices(), )

所以我想如果我能在lazy_discover_foreign_id_choices中检测到运行上下文,那么我可以选择输出一个空的选择列表。我在考虑测试sys.argv__main__.__name__,但我希望可能有更可靠的方法或API?

3 个答案:

答案 0 :(得分:8)

这是一个相当非hacky的方法(因为django已经为我们创建了标志):

import sys
def lazy_discover_foreign_id_choices():
    if ('makemigrations' in sys.argv or 'migrate' in sys.argv):
        return []
    # Leave the rest as is.

这适用于所有情况。

答案 1 :(得分:3)

我能想到的解决方案是将Django makemigrations命令子类化,以便在实际执行实际操作之前设置一个标志。

示例:

将该代码放在<someapp>/management/commands/makemigrations.py中,它将覆盖Django的默认makemigrations命令。

from django.core.management.commands import makemigrations
from django.db import migrations


class Command(makemigrations.Command):
    def handle(self, *args, **kwargs):
        # Set the flag.
        migrations.MIGRATION_OPERATION_IN_PROGRESS = True

        # Execute the normal behaviour.
        super(Command, self).handle(*args, **kwargs)

migrate命令执行相同的操作。

修改动态选择功能:

from django.db import migrations


def lazy_discover_foreign_id_choices():
    if getattr(migrations, 'MIGRATION_OPERATION_IN_PROGRESS', False):
        return []
    # Leave the rest as is.

非常黑客但很容易设置。

答案 2 :(得分:0)

使用django.db.models.signals.pre_migrate应该足以检测到<stdlib.h>命令。缺点是您不能在配置阶段使用它。