如何在Django中将分离的经纬度数据序列化为GeoJSON?
问题描述
数据库存储城市点位数据,纬度(latitude)和经度(longitude)为独立FloatField(因需求要求用户通过文本输入框输入浮点型坐标,无法使用PointField)。使用GeoDjango的serialize("geojson")方法序列化时,返回的Feature对象中geometry始终为None,示例返回数据如下:
{'type': 'Feature', 'properties': {'name': 'Ciudad Porfia', 'direction': 'Carrera 43 # 67-04 Sur', 'latitude': '4.07094', 'longitude': '-73.6695', 'city': 'Villavicencio', 'department': 'Meta', 'pk': '99'}, 'geometry': None}
当前视图核心代码:
from django.core.serializers import serialize import json ... class baseView(TemplateView): template_name = "base/maps_base.html" def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["markers_"] = json.loads(serialize("geojson", Pdv.objects.all())) return context
需将分离的经纬度转换为Point类型,生成正确的GeoJSON数据。
解决方案
方法一:给模型添加动态Point属性(推荐)
在Pdv模型中添加一个@property方法,返回Point对象,让GeoJSON序列化器识别并使用该字段作为geometry:
from django.contrib.gis.geos import Point class Pdv(models.Model): name = models.CharField(max_length=100) direction = models.CharField(max_length=200) latitude = models.FloatField() longitude = models.FloatField() city = models.CharField(max_length=100) department = models.CharField(max_length=100) @property def point(self): # GeoJSON坐标顺序为「经度,纬度」,注意不要颠倒 return Point(self.longitude, self.latitude)
修改视图中的序列化调用,指定geometry_field参数为新增的point属性:
context["markers_"] = json.loads(serialize( "geojson", Pdv.objects.all(), geometry_field='point', # 可选:指定需要包含在properties中的字段,避免冗余 fields=('name', 'direction', 'latitude', 'longitude', 'city', 'department') ))
方法二:手动构建GeoJSON结构
若不想修改模型,可在视图中遍历数据,手动生成Feature集合:
from django.contrib.gis.geos import Point import json class baseView(TemplateView): template_name = "base/maps_base.html" def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) pdv_list = Pdv.objects.all() features = [] for pdv in pdv_list: # 创建Point对象并转为GeoJSON格式 point = Point(pdv.longitude, pdv.latitude) feature = { "type": "Feature", "properties": { "name": pdv.name, "direction": pdv.direction, "latitude": pdv.latitude, "longitude": pdv.longitude, "city": pdv.city, "department": pdv.department, "pk": pdv.pk }, "geometry": json.loads(point.geojson) } features.append(feature) # 组装成标准的FeatureCollection格式 context["markers_"] = { "type": "FeatureCollection", "features": features } return context
关键注意事项
GeoJSON的坐标顺序是经度在前,纬度在后,与常规的「纬度、经度」输入顺序相反,必须严格遵守,否则点位会显示到错误位置。
内容的提问来源于stack exchange,提问作者Carlos Chavita
相关产品推荐
相关产品推荐

