
django admin 默认不为 `foreignkey` 字段生成跳转至关联对象管理页的链接,但可通过自定义 `list_display` 方法结合 `reverse` 和 `format_html` 手动实现,同时推荐配合 `list_select_related` 优化查询性能。
在 Django Admin 中,当模型包含外键(如 MyLog.user 指向 CustomUser)时,直接将字段名(如 "user")写入 list_display 仅显示字符串表示(如 CustomUser object (1)),不会自动创建指向该用户管理页面的链接——这与 Symfony Admin 等框架不同,Django 需要显式配置。
要实现点击用户名即可跳转到对应 CustomUser 的编辑页(即 /admin/myapp/customuser/1/change/),需定义一个带 HTML 链接的展示方法,并正确构造 admin URL:
from django.contrib import admin
from django.urls import reverse
from django.utils.html import format_html
@admin.register(MyLog)
class MyLogAdmin(admin.ModelAdmin):
list_display = ["id", "username_link"]
list_select_related = ["user"] # ⚡ 关键优化:避免 N+1 查询
@admin.display(ordering="user__username", description="User")
def username_link(self, obj):
if not obj.user:
return "-"
return format_html(
'{}',
reverse("admin:myapp_customuser_change", args=[obj.user.pk]),
obj.user.username or str(obj.user),
)⚠️ 注意事项:
- myapp 需替换为 CustomUser 所在应用的实际名称(如 accounts 或 users),可通过 CustomUser._meta.app_label 动态获取,但硬编码更清晰;
- 使用 obj.user.pk(而非 obj.user_id)更健壮,尤其在使用 UUIDField 或自定义主键时;
- list_select_related = ["user"] 是必备优化:它让 Django 在列表页查询中通过 JOIN 一次性获取外键数据,避免每行都触发额外数据库查询;
- 若 CustomUser 是自定义用户模型,请确保已在 settings.AUTH_USER_MODEL 中正确定义,并在 reverse() 中使用其对应 app 名,而非硬编码 'auth';
- @admin.display(ordering=...) 支持按关联字段排序(点击表头可升序/降序),提升用户体验。
最终效果:MyLog 列表页的 “User” 列将显示可点击的用户名,点击后直接进入该用户的编辑界面,完全复现了主流后台系统的便捷导航能力。










