Django Admin如何实现字段有值时只读、无值时可编辑
问题原因
你当前的get_readonly_fields逻辑只判断了「是否是编辑已有对象」,没有判断字段本身是否已经存储值,所以只要是编辑页所有指定字段都会被设为只读,空字段也被锁死,不符合需求。
实现方案
核心逻辑:编辑已有对象时逐字段校验,仅当字段存在非空存储值时才加入只读列表,空值字段保留编辑权限。
修正后的admin.py代码
from django.contrib import admin from . import models class NameAdmin(admin.ModelAdmin): model = models.Name # 统一维护需要做只读控制的字段 _readonly_control_fields = ("name", "id") def get_readonly_fields(self, request, obj=None): base_readonly = list(self.readonly_fields) # 新建对象场景,所有字段开放编辑 if not obj: return tuple(base_readonly) # 编辑场景逐字段判断值 for field in self._readonly_control_fields: val = getattr(obj, field, None) # 字段存在有效值就设为只读,空值跳过 # 注意:BooleanField存False属于有效值,不是空 if val not in (None, ""): base_readonly.append(field) return tuple(base_readonly)
模型层注意事项
你当前的模型代码有缩进错误,另外如果需要区分「未选择的空值」和「选择为否的False值」,需要给BooleanField加上空值配置,否则False会被判定为已存储值自动锁只读:
from django.db import models class Name(models.Model): # 需要区分空值和False时,按如下配置,不需要的话保留原参数即可 name = models.BooleanField(null=True, blank=True, default=None) # 注意:Django模型默认自带自增id主键,不建议手动覆盖id字段为其他类型,如果是业务字段请更换字段名 id = models.BooleanField(null=True, blank=True, default=None) def __str__(self): return f"{self.name}"
效果对应
- 新建对象页:所有控制字段可编辑,和截图1效果一致
- 保存后有值的字段:自动转为只读状态,和截图2效果一致
- 保存后仍为空的字段:保持可编辑状态,和截图3要求一致
内容的提问来源于stack exchange,提问作者Yen
相关产品推荐
相关产品推荐

