Django ModelAdmin自定义字段方法报Unknown field错误如何解决
问题原因
你使用的是Django 3.2版本,将ModelAdmin自定义展示方法直接加入fields配置是Django 4.0及以上版本才支持的特性,3.2版本中fields仅能识别模型本身定义的字段,因此会抛出未知字段错误。
可行解决方案
方案1:只读展示自定义内容(最常用)
如果不需要编辑该字段,仅需要在修改页展示内容,将自定义方法加入readonly_fields列表即可:
@admin.register(Contract) class ContractDataAdmin(admin.ModelAdmin): list_display = ("name", "status", "date_end") list_filter = ('name','status', "date_end", "headquarters_access_list") fields = ("name", "status", "date_start", "date_end", "manager_list", "buyer", "get_document_list_field", "headquarters_access_list") # 新增此行,声明自定义方法为只读字段 readonly_fields = ("get_document_list_field",) @admin.display(empty_value='???', description='关联文档列表') def get_document_list_field(self, obj): return "\n".join([c.name for c in obj.document_list.all()])
如果需要内容换行显示,可调整方法返回HTML格式并标记安全:
from django.utils.html import format_html @admin.display(empty_value='???', description='关联文档列表') def get_document_list_field(self, obj): doc_names = [c.name for c in obj.document_list.all()] return format_html("<br>".join(doc_names))
方案2:可编辑自定义字段
如果需要对该字段内容进行编辑提交,需要自定义ModelForm实现:
from django import forms from django.contrib import admin class ContractForm(forms.ModelForm): # 新增自定义可编辑字段 document_list_field = forms.CharField(label='关联文档列表', required=False, widget=forms.Textarea) class Meta: model = Contract fields = ("name", "status", "date_start", "date_end", "manager_list", "buyer", "headquarters_access_list") def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if self.instance.pk: # 初始化时填充已有值 self.fields['document_list_field'].initial = "\n".join([c.name for c in self.instance.document_list.all()]) def save(self, commit=True): instance = super().save(commit=False) # 此处编写自定义字段的提交处理逻辑,例如按换行拆分名称关联对应的Document对象 if commit: instance.save() # 多对多字段需要在instance保存后处理 doc_names = self.cleaned_data['document_list_field'].split('\n') # 示例逻辑:根据名称匹配Document对象,更新关联关系 instance.document_list.set(Document.objects.filter(name__in=doc_names)) return instance @admin.register(Contract) class ContractDataAdmin(admin.ModelAdmin): form = ContractForm list_display = ("name", "status", "date_end") list_filter = ('name','status', "date_end", "headquarters_access_list") fields = ("name", "status", "date_start", "date_end", "manager_list", "buyer", "document_list_field", "headquarters_access_list")
内容的提问来源于stack exchange,提问作者J_Zar
相关产品推荐
相关产品推荐

