回到顶部

阅读目录

django admin.ModelAdmin list_display 自定义的的字段,根据字段 字符串的数字部分按大小排序的实现方法

django admin.ModelAdmin  list_display 自定义的的字段,字段内容是 字符串的数字(比如说手机号码、身份证号码等等),排序的时候把出生年份取出来,然后按大小排序

通过 annotate 转换字段类型

ModelAdmin 中重写 get_queryset 方法,将字符串字段转换为整型,并绑定到自定义字段的排序逻辑:

from django.contrib import admin
from django.db.models import IntegerField
from django.db.models.functions import Substr, Cast

class UserAdmin(admin.ModelAdmin):
    list_display = ('phone_tail',)

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        qs = qs.annotate(
            phone_tail_int=Cast(
                Substr('phone', -4, 4),  # 显示后 4 位
                output_field=IntegerField()
            )
        )
        return qs

    def phone_tail(self, obj):
        return obj.phone[-4:]  # 显示后四位
    phone_tail.short_description = "手机尾号"
    phone_tail.admin_order_field = 'phone_tail_int'  # 绑定到转换后的整型字段

关键说明:

  1. Substr 函数

    • Substr('phone', -4, 4):从 phone 字段的倒数第4位开始截取4位(适用于类似 "13812345678" 的11位手机号)。
    • 若字段长度不固定,需调整参数(如 Substr('phone', 7, 4) 从第7位开始截取4位)。
  2. Cast 函数

    • 将截取的字符串(如 "5678")转换为 IntegerField,以便按数值大小排序。
  3. 数据库兼容性

    • PostgreSQL/MySQL:支持 Substr 和 Cast
    • SQLite:需手动实现截取逻辑(如 RIGHT(phone, 4)),可通过 RawSQL 实现:
      from django.db.models.expressions import RawSQL
      qs = qs.annotate(
          phone_tail_int=Cast(
              RawSQL("SUBSTR(phone, -4)", []),
              output_field=IntegerField()
          )
      )

其他场景适配

  • 按中间部分排序(如身份证号第7-14位出生日期):
    Substr('id_card', 7, 8)  # 截取第7位开始的8位

     

  • 处理非纯数字字段: 若字段包含非数字字符(如 "ABC1234"),需先清理数据或使用正则表达式提取数字部分(依赖数据库函数,如 REGEXP_REPLACE)。
^_^
请喝咖啡 ×

文章部分资料可能来源于网络,如有侵权请告知删除。谢谢!

前一篇: AI产品测试工程师技能与知识指南