Django Admin中TabularInline的ID列移除与自定义编号实现
解决Django Admin TabularInline的三个需求:移除ID、自定义编号列、按外键实例重新计数
刚好之前在项目里踩过类似的坑,给你一步步拆解实现:
1. 移除TabularInline自带的ID列
TabularInline默认会把关联模型的id字段显示出来,要去掉它很简单,两种方式任选:
- 方式一:用
exclude排除id字段
在你的TabularInline类里直接加一行exclude = ('id',),就能隐藏默认的ID列。 - 方式二:用
fields指定显示字段(不包含id)
如果已经明确列出了要展示的字段,只要确保fields列表里没有'id'就行,比如:fields = ('name', 'price', 'stock') # 这里不要写'id'
2. 新增按外键实例重新计数的自定义编号列
要实现每个Part实例下的关联对象编号从1开始,得靠readonly_fields搭配自定义方法来计算编号,步骤如下:
第一步:编写TabularInline类的核心代码
假设你的关联模型叫PartDetail(外键指向Part),代码示例如下:
from django.contrib import admin from .models import Part, PartDetail class PartDetailInline(admin.TabularInline): model = PartDetail exclude = ('id',) # 先移除默认ID列 readonly_fields = ('my_id',) # 把自定义编号设为只读字段 fields = ('my_id', 'name', 'spec', 'quantity') # 把编号列放在最前面 def get_queryset(self, request): # 必须指定排序规则!否则编号顺序会乱,这里按创建时间排序,你可以换成自己的字段 qs = super().get_queryset(request) return qs.order_by('created_at') def my_id(self, obj): # 未保存的新增对象(还没入库)暂时显示占位符 if not obj.pk: return '-' # 获取当前Part下的所有关联对象(严格遵循上面的排序规则) related_details = self.get_queryset(request).filter(part=obj.part) # 找到当前对象的索引,加1就是从1开始的编号 return list(related_details).index(obj) + 1 # 给编号列设置表头名称 my_id.short_description = '序号'
第二步:在Part的Admin类中注册这个Inline
@admin.register(Part) class PartAdmin(admin.ModelAdmin): inlines = [PartDetailInline]
补充:关于新增对象的临时编号
上面的代码里,未保存的新增行会显示-,因为还没存入数据库,没法确定它的最终排序位置。如果想给新增行临时显示基于表单顺序的编号(比如第一个新增行显示1,第二个显示2),可以给Admin页面加自定义JS来动态更新,但稍微复杂一点。如果你的场景里新增对象不多,用占位符基本够用;要是需要更顺滑的体验,可以自己写一段小脚本注入到Admin模板里。
内容的提问来源于stack exchange,提问作者SBrain
相关产品推荐
相关产品推荐

