R / Richie全部文章 ↑

Python · 2 分钟阅读

Admin 实现原理

Admin 看似神奇,本质是装饰器 + ContentType + ModelAdmin 的组合。

注册的本质

# 内部等价于
admin.site.register(Topic, TopicAdmin)

# 等价于
@admin.register(Topic)
class TopicAdmin(admin.ModelAdmin):
    ...

register 会把 Model 与 ModelAdmin 存入 AdminSite,再由 URLConf 自动生成对应路由。

两个核心 Python 概念

1. 装饰器

在不动原函数的前提下,给它"包一层":

import time, functools

def exec_time(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        print(f"{func.__name__} took {time.perf_counter() - start:.3f}s")
        return result
    return wrapper

@exec_time
def heavy():
    ...

带参数的装饰器 = “装饰器的装饰器”:

def exec_time(label):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            ...
            print(f"[{label}] ...")
            return result
        return wrapper
    return decorator

@admin.register 正是这类用法,它把 Model 也作为参数传入。

2. ContentType

django.contrib.contenttypes 记录"每个 App、每个 Model"的元信息,存于 django_content_type 表。

字段 含义
app_label 应用名
model 模型名(小写)

ContentTypeManager 提供了:

  • get_for_model(Model) — 通过 Model 类取 ContentType
  • get_for_id(pk) — 通过 id 取 ContentType(优先缓存)
  • model_class() — 反向得到 Model 类

Admin 的工作流

  1. register 注册时记录 Model
  2. 启动时通过 ContentType 验证 Model 存在
  3. URLConf 自动为每个 Model 生成增删改查路由
  4. ModelAdmin 决定列表页、详情页、搜索、过滤等行为

装饰器实用场景

  • 日志 / 计时 / 限流
  • 权限校验
  • 事务包裹
  • 缓存命中

Django 大量使用装饰器:@login_required、@permission_required、@csrf_exempt、Admin 注册等。