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

如何在Django ORM中无需extra将geometry转geography实现ST_DWITHIN过滤?

Django ORM替代废弃的extra()实现ST_DWITHIN地理查询

问题场景

我的Django项目中,Building模型定义了SRID为4326(WGS 84)的geometry类型字段shape,需要实现对应以下SQL的查询:

select * from building
where
    (ST_DWITHIN(shape::geography,
    ST_MakePoint(1.9217,47.8814)::geography,20))

目前只能用已标记为废弃的extra()函数实现:

Building.objects.extra(
where=[
  f"ST_DWITHIN(shape::geography, ST_MakePoint({lng}, {lat})::geography, {radius})"
])

想知道是否可以不脱离ORM框架实现该查询,比如使用Cast函数?

解决方案

完全可以通过Django GIS提供的原生ORM工具实现,无需依赖extra(),具体实现如下:

1. 导入所需工具和函数

from django.contrib.gis.db.models.functions import Cast, ST_DWithin, ST_MakePoint
from django.contrib.gis.geos import Point
from django.contrib.gis.db.models import Geography

2. 构建ORM查询语句

方式一:通过Cast转换类型

lng = 1.9217
lat = 47.8814
radius = 20

buildings = Building.objects.filter(
    ST_DWithin(
        # 将geometry字段转为geography类型
        Cast('shape', Geography(srid=4326)),
        # 构建并转换查询点为geography类型
        Cast(ST_MakePoint(lng, lat), Geography(srid=4326)),
        radius
    )
)

方式二:直接使用Point对象(更简洁)

# 创建WGS84坐标系的点对象
point = Point(lng, lat, srid=4326)

buildings = Building.objects.filter(
    ST_DWithin(
        Cast('shape', Geography(srid=4326)),
        point,
        radius
    )
)

代码说明

  • Cast('shape', Geography(srid=4326)):对应SQL中的shape::geography,将模型的geometry字段转换为geography类型
  • ST_MakePoint(lng, lat)/Point对象:Django会自动将其转换为SQL中的ST_MakePoint(...)::geography语法
  • ST_DWithin:直接映射PostGIS的ST_DWITHIN函数,用于判断两个地理对象是否在指定距离范围内

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 05:42:16