I have a model with dynamic choices, and I would like to return an empty choice list if I can guarantee that the code is being run in the event of a django-admin.py migrate / makemigrations
command to prevent it either creating or warning about useless choice changes.
Code:
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(), )
So I would think if I can detect the run context in lazy_discover_foreign_id_choices
then I can choose to output an empty choice list. I was thinking about testing sys.argv
and __main__.__name__
but I'm hoping there's possibly a more reliable way or an API?
A solution I can think of would be to subclass the Django makemigrations
command to set a flag before actually performing the actual operation.
Example:
Put that code in <someapp>/management/commands/makemigrations.py
, it will override Django's default makemigrations
command.
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)
Do the same for the migrate
command.
And modify your dynamic choices function:
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.
It is very hacky but fairly easy to setup.