You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Django ORM的annotate获取JSONField数组长度并支持排序?

解决方案

1. 定义兼容多数据库的JSON数组长度函数

不同数据库对JSON数组长度的原生函数名不同,我们封装一个自定义函数来适配:

from django.db.models import Func, IntegerField

class JSONArrayLength(Func):
    output_field = IntegerField()
    function = ''

    def as_postgresql(self, compiler, connection):
        self.function = 'jsonb_array_length'
        return super().as_postgresql(compiler, connection)

    def as_mysql(self, compiler, connection):
        self.function = 'JSON_LENGTH'
        return super().as_mysql(compiler, connection)

    def as_sqlite(self, compiler, connection):
        self.function = 'json_array_length'
        return super().as_sqlite(compiler, connection)

2. 配置Admin类实现可排序列

在admin.py中修改MapAdmin,通过数据库注解实现长度计算并支持排序:

from django.contrib import admin
from .models import Map

@admin.register(Map)
class MapAdmin(admin.ModelAdmin):
    list_display = ['id', 'locations_length']
    sortable_by = ['locations_length']

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        # 在数据库层面注解出locations数组的长度
        return qs.annotate(
            locations_length=JSONArrayLength('locations')
        )

    def locations_length(self, obj):
        return obj.locations_length
    # 设置列表表头的显示名称
    locations_length.short_description = '位置数量'

关键说明

  • 数据库注解annotate是在SQL层面计算数组长度,天然支持排序,解决了Python访问器无法排序的问题。
  • 自定义函数会自动适配PostgreSQL、MySQL、SQLite等主流数据库,无需单独修改代码。
  • 直接返回注解值比len(obj.locations)更高效,尤其在数据量较大时能减少内存消耗。

内容的提问来源于stack exchange,提问作者saschwarz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 14:52:03