假设我有以下模型:
class DenyList(models.Model):
vm_id = models.CharField(max_length=25)
我想将选项添加到vm_id
字段,但是这些选项是通过外部虚拟机注册表系统的API动态的。
所以我以以下方式完成:
class MachineChoices(object):
def get_vms(self):
if 'makemigrations' in sys.argv or 'migrate' in sys.argv:
return []
# calls api, optionally cache, return the vms
def __iter__(self):
yield from self.get_vms()
class DenyList(models.Model):
vm_id = models.CharField(max_length=25, choices=MachineChoices())
上面的工作原理是:
- 创建迁移时,它不会调用API来设置迁移文件中的所有选项
- 它是从后端驱动的,所以它可以在所有模型表单上工作,就像在django-admin中一样
- Django admin在列表显示中显示标签而不是原始值(为了提高效率,需要在
MachineChoices
中实现缓存(
我觉得这并不优雅,因为它涉及欺骗django的技巧,尤其是在迁移期间。
我知道另一种选择是使用自动完成库,但我需要使用django表单进行自定义。
那么,有什么更好的方法可以做到这一点吗?
您可以在AppConfig
中将choices
设置为None
(或空列表(。
myapp/apps.py:
import sys
from django.apps import AppConfig
class MyAppConfig(AppConfig):
name = 'myapp'
def ready(self):
if 'makemigrations' in sys.argv or 'migrate' in sys.argv:
from . import models
models.Company.street_num.field.choices = None
如果您不想具体配置每个模型字段:
if 'makemigrations' in sys.argv or 'migrate' in sys.argv:
for model in self.models.values():
for field in model._meta.fields:
field.choices = None
请记住在INSTALLED_APPS
中包含您的AppConfig
。
mysite/settings.py:
INSTALLED_APPS = [
# ...
'myapp.apps.MyAppConfig',
]