如何通过OOP全局重写Django admin.ModelAdmin的render_change_form方法
全局修改ModelAdmin render_change_form的正确OOP实现
你之前用继承的方式没生效,核心原因是:你写的NavigateFormAdmin只是个自定义基类,但Django默认还是用原生的admin.ModelAdmin注册后台,没让所有ModelAdmin都继承你的类。下面给两种符合OOP原则的解决方案:
方案1:自定义基类,业务ModelAdmin统一继承(推荐)
这是最稳妥的方式,只需要把你项目里所有注册后台的类,都改成继承你的NavigateFormAdmin,而非原生的admin.ModelAdmin:
先写通用基类:
# 比如放在项目根目录的admin_base.py from django.contrib import admin def custom_function_to_calculate(obj_id): # 你的自定义计算逻辑 return obj_id + 1 class NavigateFormAdmin(admin.ModelAdmin): def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): # 新增记录时obj是None,要加判断避免报错 if obj: context['next_record_id'] = custom_function_to_calculate(obj.id) # 调用父类原方法,完全保留原生逻辑 return super().render_change_form(request, context, add=add, change=change, form_url=form_url, obj=obj)
然后在各个app的admin.py里用这个基类:
from django.contrib import admin from .models import Article from ..admin_base import NavigateFormAdmin @admin.register(Article) class ArticleAdmin(NavigateFormAdmin): # 你的后台配置,比如列表显示字段 list_display = ('id', 'title', 'create_time')
方案2:替换全局AdminSite的默认基类(覆盖所有ModelAdmin)
如果需要让所有后台(包括Django自带的用户管理、第三方app的后台)都生效,可以自定义AdminSite并替换默认的admin站点:
- 先定义自己的AdminSite:
# admin_site.py from django.contrib.admin import AdminSite from .admin_base import NavigateFormAdmin class CustomAdminSite(AdminSite): # 设置全局默认的ModelAdmin基类 base_model_admin_class = NavigateFormAdmin
- 在urls.py里替换默认的admin路由:
from django.urls import path from .admin_site import CustomAdminSite # 实例化自定义admin站点 admin_site = CustomAdminSite(name='custom_admin') # 注册自己的Model from .models import Article admin_site.register(Article) # 注册Django自带的用户、组管理(如果需要) from django.contrib.auth.models import User, Group from django.contrib.auth.admin import UserAdmin, GroupAdmin admin_site.register(User, UserAdmin) admin_site.register(Group, GroupAdmin) urlpatterns = [ path('admin/', admin_site.urls), # 其他路由... ]
为什么猴子补丁不推荐?
- 硬抄原生方法的代码,完全违背了复用原则,Django版本更新时原生方法逻辑一变,你的代码直接报错
- 全局补丁容易和其他第三方库的修改冲突,出问题了很难排查
注意点
- 一定要判断
obj是否存在,新增记录时obj是None,直接取obj.id会报错 - 方案2需要手动注册所有需要管理的Model,包括第三方app的,不然这些Model不会出现在后台里
内容的提问来源于stack exchange,提问作者Sami
相关产品推荐
相关产品推荐

