Django admin视图中readonly字段如何设置固定随机默认值
问题原因
你的推测完全正确,两次调用生成随机值的核心逻辑是:
- Admin新增页面渲染阶段,为了展示只读的
code字段,会调用一次create_code生成初始值。但Django的readonly_fields默认只会将字段值渲染为纯文本,不会生成对应的表单输入控件,所以这个初始值不会随着表单提交到后端。 - 提交保存阶段,Django检测到表单提交的数据中没有
code字段的有效值,会再次调用字段定义的default=create_code生成新值,最终存入数据库的就是第二次生成的值。
解决方案
方案1:仅调整Admin配置(适合仅在Admin后台创建Project的场景)
重写ProjectAdmin的save_model方法,直接读取表单渲染阶段生成的初始值赋值给实例,避免二次生成:
# admin.py @admin.register(Project) class ProjectAdmin(admin.ModelAdmin): fields = ('name', 'code') readonly_fields = ('code', ) def save_model(self, request, obj, form, change): # 仅新增对象时从表单初始数据取第一次生成的code if not change: obj.code = form.initial.get('code', create_code()) super().save_model(request, obj, form, change)
方案2:调整模型保存逻辑(通用方案,适配所有创建Project的场景)
把code生成逻辑放到模型的save方法中,仅在首次保存无code的时候生成,从根源避免重复调用:
- 首先修改
models.py中的字段定义和save逻辑:
# models.py class Project(models.Model): name = models.CharField("Project name", max_length=255) # 移除default配置,新增blank=True允许初始为空 code = models.CharField("Code", max_length=10, editable=False, blank=True) def save(self, *args, **kwargs): # 仅首次保存、且没有code值的时候才生成 if not self.pk and not self.code: self.code = create_code() super().save(*args, **kwargs)
- 如果需要保留Admin新增页面预展示code的效果,再给
ProjectAdmin增加初始值生成逻辑即可:
# admin.py @admin.register(Project) class ProjectAdmin(admin.ModelAdmin): fields = ('name', 'code') readonly_fields = ('code', ) def get_initial(self, request): initial = super().get_initial(request) initial['code'] = create_code() return initial
内容的提问来源于stack exchange,提问作者Bismarck Gomes
相关产品推荐
相关产品推荐

