django model中的choices 动态从数据库中获取

你离开我真会死。 提交于 2020-04-23 22:11:41
django model中的choices 动态从数据库中获取
例如
model中,有一个type字段
type = models.CharField(max_length=255, default='BOSS', verbose_name="配置类型",choices=(('boss','boss'),('bass','bass'),))
 
现在需要从数据库中动态指定该字段的choices,取值的方法为:
# 获取计划类型列表
def get_type_list():
return PlanType.objects.values_list("name", "name")
 
错误方法:
直接
type = models.CharField(max_length=255, default='BOSS', verbose_name="配置类型",choices=get_type_list())
弊端:
数据库中修改了以后,要重启django应用才能加载
 
解决方案:
重写model的构造方法,在构造方法中指定该字段的choices即可
 
def __init__(self, *args, **kwargs):
super(PlanItemConfig, self).__init__(*args, **kwargs)
self._meta.get_field('type').choices = get_type_list()
 
问题:
调用self._meta毕竟是内部属性,不是太推荐使用
这种方法还有一个问题,定义字段的时候,方法中不能有filter,假如有filter,就会报
django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.
只能写成全部,可以在 __init__方法中,更新choices的时候,需要使用filter就用filter
我发现在数据库中修改了对应的值后,choises要刷新两次页面才能更新,具体原因未知
 
此方法还有一个致命的问题:
makemigrations的时候,会执行每个Model的init的方法,此处会执行数据库查询然后变更choices,最后体现在makemigrations生成的py文件中,在多人合作开发的项目中,会造成migrations有问题。
 
还有一种方法是self.fields['type'].choices更新choices字段。
不过这种方法也有问题,在列表中无效,必须进入编辑页面才能更新choices
 
可以定义一个ModelForm,在init方法中,更新
class ConfigForm(forms.ModelForm):
 
def __init__(self, *args, **kwargs):
super(BillingFileMQConfigForm, self).__init__(*args, **kwargs)
# 每次刷新页面都要重新获取choices的值
self.fields['type'].choices = PlanType.objects.values_list("name", "name")
 
class Meta:
model = Config
fields = '__all__'
 
然后在ModelAdmin中,指定Form即可
form = ConfigForm
 
这两种方法各有优劣,方法一可以在admin的列表中展现choices的内容,使用隐藏字段,多人makegrations会有问题。
后来改用了方法二
 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!