如何配置Django Admin模型修改页URL使用UUID替代ID
问题说明
现有所有模型继承自公共BaseModel基类,基类内置全局唯一UUID字段,定义如下:
class BaseModel(models.Model): ''' Extension of base model class ''' uuid = models.UUIDField(unique=True, default=uuid4, editable=False) ...
需要修改Django Admin默认路由逻辑,将模型修改页的URL从默认的自增ID匹配格式:.../admin/my_app/my_model/7/change/
替换为UUID匹配格式:.../admin/my_app/my_model/b6a98f1d-6b26-4399-8d68-62ec1ce12c41/change/
实现步骤
1. 定义支持UUID路由的公共Admin基类
在项目公共模块(如common/admin.py)中编写自定义Admin基类,重写对象查找逻辑与路由规则,所有需要使用UUID路由的模型Admin统一继承该类即可:
from django.contrib import admin from django.urls import path class UUIDModelAdmin(admin.ModelAdmin): # 指定对象查找字段为uuid lookup_field = "uuid" def get_object(self, request, object_id, from_field=None): # 强制使用uuid字段匹配查询对象 return super().get_object(request, object_id, from_field=self.lookup_field) def get_urls(self): default_urls = super().get_urls() # 替换默认的数字ID匹配路由,适配UUID格式,同步覆盖修改、历史、删除三个核心页面路由 custom_urls = [ path( "<uuid:object_id>/change/", self.admin_site.admin_view(self.change_view), name=f"{self.opts.app_label}_{self.opts.model_name}_change", ), path( "<uuid:object_id>/history/", self.admin_site.admin_view(self.history_view), name=f"{self.opts.app_label}_{self.opts.model_name}_history", ), path( "<uuid:object_id>/delete/", self.admin_site.admin_view(self.delete_view), name=f"{self.opts.app_label}_{self.opts.model_name}_delete", ), ] # 自定义路由优先匹配,避免被默认数字ID路由拦截 return custom_urls + default_urls
2. 模型注册时使用自定义Admin基类
在各app的admin.py中注册模型时,继承上述UUIDModelAdmin即可,原有Admin配置逻辑不受影响:
from django.contrib import admin from .models import MyModel from common.admin import UUIDModelAdmin @admin.register(MyModel) class MyModelAdmin(UUIDModelAdmin): # 原有配置照常编写,例如列表展示字段、筛选器等 list_display = ["uuid", "create_time", "name"] list_filter = ["create_time"]
注意事项
- 该方案不需要修改模型原有主键结构,只要模型存在
unique=True的uuid字段即可正常运行,你当前的BaseModel定义已经满足要求 - 未继承
UUIDModelAdmin的模型仍会使用默认的自增ID路由规则,不会互相干扰 - Admin列表页自动生成的详情页跳转链接、操作跳转链接会自动适配新的UUID路由,不需要额外修改模板或跳转逻辑
- 路由使用Django内置的
uuid路径转换器,非标准UUID格式的请求会直接返回404,不存在非法参数注入风险
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

