有这样一个需求, Django 后台 admin 有一个 select 字段, 其备选项是某个系统路径下的文件名, 因此下拉列表的备选项是动态的.
而常规的 select 声明方式如下, 其备选项 choices 是静态的. 如果目标路径的文件发生变动, 必须重启 django 才能获得更新后的下拉列表.
name = models.CharField(max_length=64, choices = (('0','file1'),('0','file1')))
一个自然思路就是, 重载admin的 formfield_for_choice_field()
, 在函数内部调用下拉列表获取方法. 但问题是, 一旦选择的值不在上面声明的 choices
中, 表单验证就会失败.
正确的做法是取消 choices 约束, 将字段变成纯字符串型.
name = models.CharField(max_length=64)
这时候, admin 对name的 widget 会由 select 变为 input, 这不是我们想要的. 所以需要手动指定:
class RouteForm(forms.ModelForm):
class Meta:
widgets = {
'name': forms.Select(),
}
class RouteAdmin(TreeAdmin):
form = RouteForm
def formfield_for_dbfield(self, db_field, request, **kwargs):
if db_field.name == 'name':
choices = TextChoices(
'RouteName',
get_files()
)
kwargs['widget'].choices = choices.choices
return super().formfield_for_dbfield(db_field, request, **kwargs)
这时候, 需要重载的函数就变为了 formfield_for_dbfield()
, 按照上述方式构造的admin,就能够实现业务需求.
网友评论