Django Admin如何从索引页与应用页排除模型且保留增改视图?
实现方案(完全基于Django原生API,无hack、无第三方依赖)
完全可以实现,不需要翻模板改来改去,也不用写奇怪的猴子补丁,只要在目标隐藏模型对应的ModelAdmin类里重写两个官方预留的公开方法就行。
要实现的目标拆解
我们最终要达成三个效果,刚好都对应Django Admin原生的扩展点:
- 从Admin首页、单应用列表页彻底移除目标模型的展示入口
- 关闭模型默认的列表视图(也就是changelist/
list_view)路由,彻底禁用不需要的列表能力 - 完整保留新增视图、修改视图的访问能力和原生权限校验,不管是从inline跳转过去,还是直接输入URL访问都正常
具体代码实现
举个例子,如果你要隐藏的是OrderItem模型(这类模型一般都是作为关联项塞在父模型的inline里使用),对应的ModelAdmin写法如下:
from django.contrib import admin from .models import OrderItem @admin.register(OrderItem) class OrderItemAdmin(admin.ModelAdmin): # 这里正常写你需要的配置就行:比如表单字段、过滤条件、搜索逻辑啥的,全不受影响 # list_display = ["order", "product", "price"] # search_fields = ["product__name"] # 第一步:移除列表视图(changelist)的路由,彻底禁用list_view def get_urls(self): default_urls = super().get_urls() # 拼接当前模型对应的changelist路由名称 changelist_route_name = ( f"{self.model._meta.app_label}_{self.model._meta.model_name}_changelist" ) # 过滤掉对应名称的路由,剩下的add/change/delete等路由完全保留 return [ route for route in default_urls if getattr(route, "name", None) != changelist_route_name ] # 第二步:让目标模型不出现在索引页、应用列表页 def get_model_perms(self, request): # 这个方法是Django预留的、专门给模板/列表页生成权限字典的扩展点 # 原生实现会返回用户对当前模型的add/change/delete/view四个权限状态 # 我们直接返回全False的字典,让列表生成逻辑判定这个模型没有展示权限 # 注意:这个方法不会参与add/change视图的内部权限校验,完全不影响两个视图的正常访问 return { "add": False, "change": False, "delete": False, "view": False, }
为什么这套方法不算hack?
- 重写
get_urls是Django文档明确支持的自定义Admin路由的标准方式,本来就允许你对默认生成的路由做增删改 - 重写
get_model_perms也是Django公开的权限扩展点,这个方法的设计用途就是让你自定义模板展示时的权限判断逻辑,根本不会侵入视图层的权限校验 - 整个过程没有修改Django源码、没有在运行时动态替换方法、没有硬改模板逻辑,完全走正常的类继承扩展路径
实际效果验证
按照上面的配置做完后:
- 访问
/admin/首页、对应应用的列表页,完全看不到目标模型的入口 - 直接访问原模型列表页路径(
/admin/<应用标签>/<模型名>/),会返回404,符合不需要启用list_view的需求 - 从父模型的inline里跳转新增、修改目标模型对象的流程完全正常,直接输入新增、修改路径的访问逻辑、权限校验和原本没有任何区别
- 所有原有的ModelAdmin配置(比如表单校验、字段过滤、自定义动作啥的)都能正常生效
内容的提问来源于stack exchange,提问作者wowkin2
相关产品推荐
相关产品推荐

