原文作者:我辈理想
版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。
Django数据操作-ORM
【Django开发入门】ORM的增删改查和批量操作
【Django开发入门】ORM查询分页以及返回Json格式
【GeoDjango框架解析】空间方法的ORM查询
文章目录
前言
通过前面的ORM使用,我们看到ORM在开发中可以提供很大便利,基于国内讲解Geodjango使用的教程比较少,我这里整理了基于postgis数据库的orm空间查询的相关方法。
如果使用的是其他数据库,不能保障空间方法生效。
一、开发环境搭建
开发环境很是重要,尤其是geodjango环境搭建会出现很多问题,我在其他博客中已经给出相关介绍,可以参考。
【GeoDjango框架解析】配置geodjango开发环境
【Linux安装数据库】Ubuntu安装postgresql并连接navicat添加链接描述
【GeoDjango框架解析】conda环境下安装psycopy2版本问题
二、参数查询空间方法
因为业务的关系,我这里主要介绍的都是包含的处理方法,包括点、圆、多边范围查询。
1.点的查询
search_dict = {}
# point是history表的一个字段 models.PointField("点", null=True)
q = Q(geom__contains=history.point)
A.objects.filter(**search_dict).filter(q)
2.圆的查询
search_dict = {}
# point是history表的一个字段 models.PointField("点", null=True)
# diameter是圆的半径,单位m
q = Q(geom__distance_lte=(history.point, str(history.diameter)))
A.objects.filter(**search_dict).filter(q)
3.多边和多多边
search_dict = {}
# geometrycollection是history表的一个字段
# geometrycollection = models.GeometryCollectionField('混合数据', null=True)
q = Q(geom__intersects=history.geometrycollection)
A.objects.filter(**search_dict).filter(q)
三、聚合的空间方法
在geodjango中使用的空间方法都是基于aggregate的方法,这里需要掌握django的聚合方法。
其实django官网给出了相关方法,但是没有相关样例,使用过程中很难嵌入orm查询。我这里找到一个中文版的文档。接下来我会以我实际使用的相关功能来介绍。
1.IsValid是否是有效图形
cover = pics.aggregate(isv=IsValid('geom'))
print(cover.isv) # 结果是True或False
2.MakeValid建立有效几何图形
cover = pics.aggregate(un=MakeValid('geom'))
3.Envelope确认外接多边形
geodjango中确认最小外接多边形的方法是envelope,在geodjango中一共有4种。
django.contrib.gis.db.models.functions.Envelope (Python 类, in 地理数据库功能)
django.contrib.gis.gdal.Envelope (Python 类, in GDAL API)
django.contrib.gis.gdal.OGRGeometry.envelope (Python 属性, in GDAL API)
django.contrib.gis.geos.GEOSGeometry.envelope (Python 属性, in 地理信息系统API)
# 第一种
from django.contrib.gis.db.models.functions import Envelope
pic = PicData.objects.annotate(g=Envelope('geom')).get(id=26497)
pic.geom = pic.g
pic.save()
# 第二种
from django.contrib.gis.gdal import Envelope
g = Envelope(pic.geom)
# 第三种和第四种
g= OGRGeometry(str(pic_data["geom"]), srid=4326).envelope
g= GEOSGeometry(str(pic_data["geom"]), srid=4326).envelope
4.Union建立2个图形并集
django.contrib.gis.db.models.functions.Union (Python 类, in 地理数据库功能)
django.contrib.gis.db.models.Union (Python 类, in GIS查询集API参考)
django.contrib.gis.gdal.OGRGeometry.union (Python 方法, in GDAL API)
django.contrib.gis.geos.GEOSGeometry.union (Python 方法, in 地理信息系统API)
# 第一种
from django.contrib.gis.db.models.functions import Union
cover = pics.aggregate(un=Union(MakeValid('geom')))
# 第二种,search_geom是GEOSGeometry类型
from django.contrib.gis.db.models import Union
cover = pics.aggregate(un=Union(MakeValid('geom'), search_geom))
# 第三种和第四种,search_geom是GEOSGeometry类型
g= OGRGeometry(str(pic_data["geom"]), srid=4326).union(search_geom)
g= GEOSGeometry(str(pic_data["geom"]), srid=4326).union(search_geom)
5.Intersection建立2个图形交集
django.contrib.gis.db.models.functions.Intersection (Python 类, in 地理数据库功能)
django.contrib.gis.gdal.OGRGeometry.intersection (Python 方法, in GDAL API)
django.contrib.gis.geos.GEOSGeometry.intersection (Python 方法, in 地理信息系统API)
# 第一种,search_geom是GEOSGeometry类型
cover = pics.aggregate(it=Intersection(Union(MakeValid('geom')), search_geom))
# 第二种和第三种
cover = OGRGeometry(str(pic_data["geom"]), srid=4326).intersection(search_geom)
cover = GEOSGeometry(str(pic_data["geom"]), srid=4326).intersection(search_geom)
6.Transform转换SRID坐标系,面积计算
虽然官方文档提供了相关函数,但是那个给出的面积不是真实的面积,需要使用Transform转换为3857坐标系后的面积
每条数据geom字段计算面积
cover = pics.aggregate(tf=Transform(Intersection(Union(MakeValid('geom')), search_geom), srid=3857))
cover_area = cover['tf'].area
合并geom字段计算面积
cover = pics.aggregate(tf=Transform(Intersection(Union(MakeValid('geom')), search_geom), srid=3857))
cover_area = cover['tf'].area
7.Buffer建立缓冲区
country = County.objects.filter(name='中华人民共和国', type='country').first()
# 判断点是否在国界线内,point_ 的结果是True 和False
point = 'POINT(116 38)'
point_ = country.geom.contains(point)
# 因为country的几何图形可能存在不规则,需要用buffer,width的单位是度数(经纬度)
point_ = country.geom.buffer(width=0.01).contains(point)
8.simplify矢量简化
simplify是GEOSGeometry的方法,根据tolerance参数获取简化的几何图形,返回依然是GEOSGeometry,tolerance的参数范围是0-1,参数越小,越接近原几何图形,默认值为0。
history = HistoryData.objects.annotate(gt=MakeValid('geometrycollection'),
tf=Transform('gt', srid=3857)).get(
id=request.query_params.get('hid'))
history.geometrycollection.simplify(tolerance=0.05)
9.其他
pic_in = pics.aggregate(in_area=Area(Intersection(Union(MakeValid('geom')), search_geom)))
print('pic_in', pic_in['in_area'])
cover_area = pic_in['in_area'].sq_km
cover_area = pic_in['in_area'].sq_m