You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django Admin修改列表中隐藏指定状态选项

解决Admin面板中限制状态选择的问题

要实现管理员只能选择前3种状态(Unproven、In progress、In line for deletion),同时保留模型层面完整的choices(因为Celery任务需要设置DELETED状态),你可以通过自定义Admin表单来覆盖status字段的可选值,下面提供两种常用的实现方式:

方式一:自定义ModelForm

创建一个Admin专用表单,在表单中重新定义status字段的choices,只保留需要的三个选项:

from django import forms
from .models import UserDeleteRequest, UNPROVEN, IN_PROGRESS, IN_LINE_FOR_DELETE

class UserDeleteRequestAdminForm(forms.ModelForm):
    class Meta:
        model = UserDeleteRequest
        fields = "__all__"
    
    # 重定义status字段,仅保留前三个状态选项
    status = forms.ChoiceField(
        choices=[
            (UNPROVEN, "Unproven"),
            (IN_PROGRESS, "In progress"),
            (IN_LINE_FOR_DELETE, "In line for deletion"),
        ],
        required=True,
    )

接着在Admin类中指定使用这个表单:

@admin.register(UserDeleteRequest)
class UserDeleteRequestAdmin(admin.ModelAdmin):
    form = UserDeleteRequestAdminForm  # 绑定自定义表单
    list_display = ("status", "responsible_user")
    fields = ("delete_user", "status", "responsible_user", "delete_reason")
    readonly_fields = ("responsible_user", "delete_user", "delete_reason")
    
    def has_add_permission(self, request):
        return False
    
    def has_delete_permission(self, request, obj=None):
        return False
    
    def save_model(self, request, obj, form, change):
        # 修正原代码的条件判断错误:原写法"obj.status == 3 or 2"永远为True
        if obj.status in (IN_PROGRESS, IN_LINE_FOR_DELETE):
            obj.responsible_user = request.user
        super().save_model(request, obj, form, change)

方式二:重写Admin的get_form方法

如果不想单独创建ModelForm,也可以在Admin类中动态修改字段的choices:

from .models import UNPROVEN, IN_PROGRESS, IN_LINE_FOR_DELETE

@admin.register(UserDeleteRequest)
class UserDeleteRequestAdmin(admin.ModelAdmin):
    list_display = ("status", "responsible_user")
    fields = ("delete_user", "status", "responsible_user", "delete_reason")
    readonly_fields = ("responsible_user", "delete_user", "delete_reason")
    
    def has_add_permission(self, request):
        return False
    
    def has_delete_permission(self, request, obj=None):
        return False
    
    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        # 动态替换status字段的可选值
        form.base_fields['status'].choices = [
            (UNPROVEN, "Unproven"),
            (IN_PROGRESS, "In progress"),
            (IN_LINE_FOR_DELETE, "In line for deletion"),
        ]
        return form
    
    def save_model(self, request, obj, form, change):
        if obj.status in (IN_PROGRESS, IN_LINE_FOR_DELETE):
            obj.responsible_user = request.user
        super().save_model(request, obj, form, change)

额外优化建议

  • 针对已处于DELETED状态的记录,你可以让status字段变成只读,避免管理员误修改:
    def get_readonly_fields(self, request, obj=None):
        readonly_fields = super().get_readonly_fields(request, obj)
        if obj and obj.status == 4:  # 或使用DELETED常量
            return readonly_fields + ("status",)
        return readonly_fields
    
  • 模型层面的_STATUS无需修改,这样Celery任务设置DELETED状态后,Admin列表页仍能正常显示"Deleted"文本,只是编辑表单中无法选择该选项。

内容的提问来源于stack exchange,提问作者GrinRuslan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:48:20