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

GeoDjango如何加载多CRS的.shp文件并转为WGS84的GeoJSON?

推荐方案:GDAL/OGR生态(ogr2ogr 或 GeoDjango DataSource)

针对你的需求——在Django中将不同CRS的SHP文件转换为WGS84(EPSG:4326)的GeoJSON,再给Leaflet展示,我最推荐GDAL/OGR相关的方案,这是空间数据处理领域的标准工具链,CRS转换支持全面且可靠。下面逐个分析你提到的三个方案:

1. ogr2ogr(最直接高效,优先推荐)

ogr2ogr是GDAL工具集里的核心转换工具,对各种CRS的支持非常完善,能一键完成SHP到GeoJSON的格式转换+CRS转WGS84,完全不需要自己处理坐标计算。你有两种使用方式:

方式一:直接在Django中调用命令行(简单快速)

在Django视图里通过subprocess调用ogr2ogr命令,生成GeoJSON后读取内容返回给前端:

import subprocess
import os
from django.http import HttpResponse

def shp_to_geojson(request, shp_path):
    # 临时输出GeoJSON路径(可以用Django的临时文件管理)
    temp_geojson = "/tmp/output.geojson"
    # 执行ogr2ogr命令:转换为GeoJSON,目标CRS设为WGS84
    subprocess.run([
        "ogr2ogr",
        "-f", "GeoJSON",
        "-t_srs", "EPSG:4326",
        temp_geojson,
        shp_path
    ], check=True)
    
    # 读取生成的GeoJSON内容
    with open(temp_geojson, "r") as f:
        geojson_str = f.read()
    
    # 删除临时文件(可选)
    os.remove(temp_geojson)
    
    return HttpResponse(geojson_str, content_type="application/json")

方式二:使用GDAL的Python绑定(osgeo.ogr),更集成化

如果不想调用外部命令,可以直接用Python的GDAL库(GeoDjango默认已经依赖这个),在代码里完成转换:

from osgeo import ogr, osr
import json
from django.http import HttpResponse

def shp_to_geojson(request, shp_path):
    # 打开SHP文件
    driver = ogr.GetDriverByName("ESRI Shapefile")
    data_source = driver.Open(shp_path, 0)  # 0表示只读
    layer = data_source.GetLayer()
    
    # 设置源CRS和目标CRS(WGS84)
    source_crs = layer.GetSpatialRef()
    target_crs = osr.SpatialReference()
    target_crs.ImportFromEPSG(4326)
    transform = osr.CoordinateTransformation(source_crs, target_crs)
    
    # 构建GeoJSON结构
    geojson = {
        "type": "FeatureCollection",
        "features": []
    }
    
    # 遍历所有要素
    for feature in layer:
        # 转换几何坐标
        geom = feature.GetGeometryRef()
        geom.Transform(transform)
        
        # 获取属性
        properties = {}
        for i in range(feature.GetFieldCount()):
            field_name = feature.GetFieldDefnRef(i).GetName()
            properties[field_name] = feature.GetField(i)
        
        # 添加到FeatureCollection
        geojson["features"].append({
            "type": "Feature",
            "geometry": json.loads(geom.ExportToJson()),
            "properties": properties
        })
    
    return HttpResponse(json.dumps(geojson), content_type="application/json")

2. GeoDjango的DataSource

其实GeoDjango的DataSource就是对GDAL/OGR的封装,和上面的osgeo.ogr方案本质一样,但更贴合GeoDjango的开发习惯。你可以用它来读取SHP,然后结合Django的空间工具完成CRS转换:

from django.contrib.gis.gdal import DataSource, SpatialReference
import json
from django.http import HttpResponse

def shp_to_geojson(request, shp_path):
    ds = DataSource(shp_path)
    layer = ds[0]
    # 设置目标CRS为WGS84
    target_srs = SpatialReference(4326)
    
    geojson = {
        "type": "FeatureCollection",
        "features": []
    }
    
    for feat in layer:
        # 转换几何
        geom = feat.geom.transform(target_srs, clone=True)
        # 获取属性
        props = dict(feat.fields.items())
        # 添加到GeoJSON
        geojson["features"].append({
            "type": "Feature",
            "geometry": json.loads(geom.json),
            "properties": props
        })
    
    return HttpResponse(json.dumps(geojson), content_type="application/json")

这个方案的好处是和GeoDjango的生态完全兼容,如果你的项目已经在用GeoDjango,用这个会更顺手。

3. PyShp(不推荐用于多CRS场景)

PyShp的优势是轻量,但它本身不支持CRS解析和转换,你需要额外依赖pyproj库来处理坐标转换,还要自己解析SHP附带的.prj文件来获取源CRS信息,步骤繁琐且容易出错。比如你需要先读取.prj文件,用pyproj创建转换对象,然后逐个遍历shape的坐标点进行转换,这种方式只适合简单的、已知CRS的场景,面对多个不同CRS的SHP文件时,维护成本很高,所以不推荐。

总结

  • 如果追求最快上手、最少代码,选ogr2ogr命令行方式;
  • 如果要和GeoDjango深度集成,选DataSource方案;
  • PyShp只适合不需要CRS转换的简单SHP处理场景,你的需求下不建议使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 09:02:38