Django Admin未调用模型中重写的_get_FIELD_display方法问题
Django Admin未调用重写的get_FIELD_display方法的解决办法
问题分析
你在模型X中重写了get_status_display()方法,用于将DELIVERED状态的显示文本替换为Completed!,该方法在序列化器中正常工作,但Django Admin并未调用它,原因可能是:
- 你使用的
FSMField是自定义字段(来自django-fsm),Django Admin对这类字段的默认处理逻辑是直接读取字段本身的choices属性,而非调用模型的get_FIELD_display()方法; - 模型代码中存在笔误:
get_status_display里引用了Order.STATUSES,但当前模型是X,这会导致方法执行出错,Admin自动 fallback 到默认的choices显示。
解决方案
1. 修正模型中的笔误
首先把模型里的Order.STATUSES替换为X.STATUSES,确保方法能正常执行:
def get_status_display(self) -> str: """ Overrides to replace X.STATUSES.DELIVERED with Completed as it's confusing.""" value = self.status if value == X.STATUSES.DELIVERED: return _("Completed!") choices_dict = dict(X.STATUSES) # force_str() to coerce lazy strings. return force_str(choices_dict[value], strings_only=True)
2. 在ModelAdmin中显式调用自定义显示方法
如果是Admin列表页不显示自定义文本,在ModelAdmin的list_display中使用自定义函数,显式调用模型的get_status_display():
from django.contrib import admin from .models import X class XAdmin(admin.ModelAdmin): # 替换原有的'status'为自定义显示函数 list_display = ('id', 'custom_status', 'created', 'modified') def custom_status(self, obj): return obj.get_status_display() # 设置列表页表头名称 custom_status.short_description = 'Status' admin.site.register(X, XAdmin)
3. 适配详情编辑页的显示
如果需要在Admin的详情编辑页也显示自定义文本(由于status字段设置了protected=True,通常为只读状态),可以添加只读字段并绑定自定义显示:
class XAdmin(admin.ModelAdmin): list_display = ('id', 'custom_status', 'created', 'modified') readonly_fields = ('custom_status',) # 替换原有'status'字段为自定义只读字段 fields = ('custom_status', 'created', 'modified') def custom_status(self, obj): return obj.get_status_display() custom_status.short_description = 'Status'
4. 动态修改表单choices(如需保留编辑权限)
如果需要保留status字段的编辑权限(尽管protected=True可能限制状态转换),可以自定义ModelForm来动态修改choices:
from django import forms from django.contrib import admin from .models import X class XAdminForm(forms.ModelForm): class Meta: model = X fields = '__all__' def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 遍历choices,替换DELIVERED的显示文本 updated_choices = [] for value, label in self.fields['status'].choices: if value == X.STATUSES.DELIVERED: updated_choices.append((value, _("Completed!"))) else: updated_choices.append((value, label)) self.fields['status'].choices = updated_choices class XAdmin(admin.ModelAdmin): form = XAdminForm list_display = ('id', 'get_status_display', 'created', 'modified') admin.site.register(X, XAdmin)
内容的提问来源于stack exchange,提问作者Ibrahim Abou Elenein
相关产品推荐
相关产品推荐

