在 migrate/makemigrations 命令的上下文中检测代码是否被 运行
Detect whether code is being run in the context of migrate/makemigrations command
我有一个带有动态选择的模型,如果我能保证在 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?
我能想到的一个解决方案是将 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.
它非常笨拙,但设置起来相当容易。
这是一个相当简单的方法来做到这一点(因为 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.
这应该适用于所有情况。
使用django.db.models.signals.pre_migrate
应该足以检测migrate
命令。缺点是你不能在配置阶段使用它。
我有一个带有动态选择的模型,如果我能保证在 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?
我能想到的一个解决方案是将 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.
它非常笨拙,但设置起来相当容易。
这是一个相当简单的方法来做到这一点(因为 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.
这应该适用于所有情况。
使用django.db.models.signals.pre_migrate
应该足以检测migrate
命令。缺点是你不能在配置阶段使用它。