Django ModelAdmin新增页面刷新前后字段显示异常问题
问题原因
核心问题出在ModelAdmin是全局单例实例,你直接在get_form里修改self.fields会污染全局状态:首次请求时,实例初始化顺序导致self.fields的修改没能及时生效,所以加载了全部字段;刷新后实例状态已更新,才会显示指定字段。另外,ServiceProviderForm的Meta里exclude=("",)等于不排除任何字段,也会在ModelAdmin字段设置失效时触发全量字段加载。
修复方案
1. 不修改ModelAdmin实例的self.fields,通过kwargs传递字段配置
不要直接给self.fields赋值,而是把计算好的字段列表通过kwargs['fields']传给父类get_form,这样不会污染全局实例状态,每次请求都会用当前计算的字段:
class ServiceProviderAdmin(admin.ModelAdmin): ... def get_form(self, request, obj=None, **kwargs): # 计算当前请求需展示的字段,不修改self.fields fields = ( "name_registration", "name_social", "nome_usual", ("gender","document"), "department", "department_aditionals", "picture", "active", ) if request.user.has_perm("rh.can_edit_secondary_mail"): fields = fields + ("email_secondary",) # 将字段通过kwargs传入,覆盖默认配置 kwargs['fields'] = fields self.form = ServiceProviderFormFactory(request.user) return super().get_form(request, obj=obj, **kwargs)
2. 优化表单Meta配置(可选但推荐)
既然已经在ModelAdmin里明确指定了字段,把表单的Meta改为fields = '__all__',避免exclude=("",)带来的潜在问题:
def ServiceProviderFormFactory(user): class ServiceProviderForm(forms.ModelForm): ... def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) ... class Meta: model = ServiceProvider fields = '__all__'
修复逻辑说明
- 不修改
self.fields就不会因为单例实例的状态共享导致首次请求的字段配置失效,每次请求都会基于当前用户权限计算字段并传递给表单生成逻辑。 - 调整表单Meta配置后,表单会优先使用ModelAdmin传递的
fields参数,不会因为exclude为空而加载全部字段,从根源避免重型查询触发。
内容的提问来源于stack exchange,提问作者Neto
相关产品推荐
相关产品推荐

