如何让Django-admin的@admin.display装饰器支持多列排序?
Django Admin 自定义全名字段并支持多字段排序
我有一个包含last_name和first_name字段的数据库模型,想要在Django Admin中显示“姓氏, 名字”格式的全名,并且该列支持按姓氏+名字排序。
用@admin.display装饰器实现时,只传入单个排序字段(如ordering="last_name")可以正常工作,但同姓用户的顺序会混乱。尝试传入列表或元组作为ordering参数(如ordering=["last_name", "first_name"])时,会抛出'tuple' object has no attribute 'startswith'错误。
方法1:升级到支持多字段ordering的Django版本
从Django 3.2开始,@admin.display的ordering参数支持传入字符串的元组/列表。如果你使用的是该版本及以上,直接使用元组(推荐,避免列表带来的潜在问题)即可:
@admin.display(description="全名", ordering=('last_name', 'first_name')) def full_name(self, obj): return f"{obj.last_name}, {obj.first_name}"
方法2:旧版Django兼容方案(不升级版本)
如果无法升级Django,可通过重写ModelAdmin的get_ordering方法,手动处理自定义字段的排序逻辑:
class YourModelAdmin(admin.ModelAdmin): list_display = ('full_name', '其他字段') @admin.display(description="全名") def full_name(self, obj): return f"{obj.last_name}, {obj.first_name}" def get_ordering(self, request): # 获取当前排序参数,o是Django Admin默认的排序参数名 order_param = request.GET.get('o') # 自定义字段在list_display中的索引,这里full_name是第0个元素 full_name_index = str(self.list_display.index('full_name')) if order_param == full_name_index: # 升序:按last_name、first_name排序 return ('last_name', 'first_name') elif order_param == '-' + full_name_index: # 降序:按last_name、first_name倒序 return ('-last_name', '-first_name') # 其他情况使用默认排序 return super().get_ordering(request)
说明
- 方法1更简洁,是官方推荐的方式,优先考虑升级Django版本。
- 方法2通过拦截排序请求,将自定义字段的排序映射到真实的模型字段,兼容旧版Django。
内容的提问来源于stack exchange,提问作者roughdog
相关产品推荐
相关产品推荐

