Django 1.11 Admin创建对象时自动计算并隐藏只读age字段问题
解决Django Admin中隐藏字段并自动填充的问题
你遇到的问题核心在于:当你用exclude = ('age',)时,这个字段会被彻底排除出表单的处理流程——哪怕你在clean()方法里给cleaned_data['age']赋了值,也不会被传递到模型实例中完成保存。
要实现创建时隐藏age字段、自动计算值,查看实例时age可见的需求,推荐改用ModelAdmin的save_model钩子方法来处理年龄计算,这样既不用在表单里暴露字段,又能确保值被正确存入数据库。
修改后的完整代码如下:
# admin.py from django.contrib import admin from .models import Person from dateutil.relativedelta import relativedelta import datetime class PersonAdmin(admin.ModelAdmin): # 明确指定创建表单要显示的字段,不包含age,实现隐藏效果 fields = ('name', 'birthdate') def save_model(self, request, obj, form, change): # 在保存实例前计算并赋值年龄 if obj.birthdate: obj.age = str(relativedelta(datetime.date.today(), obj.birthdate).years) # 调用父类方法完成最终保存 super().save_model(request, obj, form, change) admin.site.register(Person, PersonAdmin)
方案优势说明
fields = ('name', 'birthdate')直接限定了表单可见字段,age不会出现在创建页面,完全符合隐藏需求。save_model是Django Admin原生提供的保存钩子,在模型实例写入数据库前触发,这里直接给obj.age赋值,能确保值被正确持久化。- 查看实例详情时,Django Admin默认会展示模型的所有字段(除非你额外配置了
fieldsets或list_display做限制),所以age会正常显示。
如果你更倾向于用ModelForm实现,也可以把age设为隐藏字段(但用户通过开发者工具仍能看到,安全性稍弱),代码示例如下:
class PersonForm(forms.ModelForm): # 把age设为隐藏输入框,前端不可见但仍会被表单处理 age = forms.CharField(widget=forms.HiddenInput(), required=False) def clean(self): cleaned_data = super().clean() birthdate = cleaned_data.get('birthdate') if birthdate: cleaned_data['age'] = str(relativedelta(datetime.date.today(), birthdate).years) return cleaned_data class PersonAdmin(admin.ModelAdmin): form = PersonForm fields = ('name', 'birthdate', 'age')
整体来说第一种方案逻辑更清晰,也能避免前端篡改的潜在风险,更推荐使用。
内容的提问来源于stack exchange,提问作者Demetris
相关产品推荐
相关产品推荐

