如何在Django admin中将多对多关联字段展示为可跳转超链接
Django Admin多对多字段渲染为可点击超链接方案
问题根因
返回列表格式的结果时,Django admin会将列表整体转为普通字符串输出,不会对列表内的单个安全HTML对象做渲染,因此只能看到文本无法生成可点击链接;返回单个format_html生成的安全字符串时可以被正常识别渲染。
直接修复方案
修改你的Admin类自定义字段方法,使用Django内置的format_html_join方法批量拼接多对多关联对象的链接,代码如下:
from django.contrib import admin from django.urls import reverse from django.utils.html import format_html_join from .models import MyObject, RelatedObject class MyAdmin(admin.ModelAdmin): # 注意单个元素的元组需要加逗号,否则会被识别为字符串触发报错 list_display = ("rel",) def rel(self, obj): # 第一个参数为多个链接之间的分隔符,可根据需要修改为换行符<br>等其他内容 return format_html_join( ", ", '<a href="{}">{}</a>', ( (reverse("admin:<替换为你的APP名>_relatedobject_change", args=[item.id]), item.name) for item in obj.related.all() ) ) # 自定义列表页该列的表头名称 rel.short_description = "关联对象" # 可选优化:添加prefetch_related避免多对多字段查询的N+1问题 def get_queryset(self, request): return super().get_queryset(request).prefetch_related("related")
通用复用方案
如果需要在多个模型、多个多对多字段上复用该能力,可以封装通用生成方法,无需重复编写逻辑:
from django.utils.html import format_html_join from django.urls import reverse def generate_m2m_link_field(field_name, app_label, model_name, separator=", "): """ 生成多对多字段可点击链接的通用方法 :param field_name: 多对多字段的字段名 :param app_label: 关联模型所属的APP名称 :param model_name: 关联模型的小写类名 :param separator: 多个链接之间的分隔符 """ def _inner_field(self, obj): return format_html_join( separator, '<a href="{}">{}</a>', ( (reverse(f"admin:{app_label}_{model_name}_change", args=[item.id]), str(item)) for item in getattr(obj, field_name).all() ) ) _inner_field.short_description = field_name.replace("_", " ").title() return _inner_field # 使用示例 class MyAdmin(admin.ModelAdmin): list_display = ("rel",) # 直接调用通用方法生成对应的字段处理逻辑 rel = generate_m2m_link_field("related", "替换为你的APP名", "relatedobject")
注意事项
- 代码中的
<替换为你的APP名>需要替换为RelatedObject模型所属的Django应用的名称 - 若不需要使用第三方linkify工具,以上原生方案完全可满足需求,无需额外依赖
- 若需要关联对象之间换行展示,将分隔符从
,改为<br>即可
内容的提问来源于stack exchange,提问作者Shmuelt
相关产品推荐
相关产品推荐

