代码之家  ›  专栏  ›  技术社区  ›  trubliphone

如何有效地将geopandas中的数据保存到django(从shapely转换到geodjango)?

  •  0
  • trubliphone  · 技术社区  · 6 年前

    我正在处理GIS数据/ geopandas 并将其储存在各种 Django 模型。 地潘达斯 使用 shapely 在引擎盖下 德扬戈 没有。

    以下是一些代码:

    import geopandas as gpd
    from django.contrib.gis.db import models
    
    class MyModel(models.Model):
      geometry = models.PolygonField()
      name = models.CharField(max_length=255, null=False, unique=True)
      some_property = models.IntegerField()
    
    gdf = gpd.read_file("some_data.geojson")
    # ...do some stuff w/ gdf...
    
    for data in gdf.to_dict("records"):
      name = data.pop("name")
      MyModel.objects.create_or_update(
        name=name,
        defaults=data,
      )
    

    上述操作将失败,并出现以下错误:

    TypeError:无法将MyModel SpatialProxy(多边形)的值设置为类型:<班上的人身材匀称。几何学多边形多边形'>

    除非我添加一些讨厌的代码,比如:

    from django.contrib.gis.geos import fromstr, Polygon 
    data["geometry"] = Polygon(fromstr(str(data["geometry"])))
    

    有没有办法避免这种情况并直接从 匀称 德扬戈 ?


    编辑 :

    以下是一些价值观:

    >> data["geometry"]
    <shapely.geometry.polygon.Polygon object at 0x7fb374f41908>
    >> str(data["geometry"])
    'POLYGON ((-4.337076919429241 53.41842814531255, -4.336698521348041 53.4182242737367, ....))'
    >> fromstr(str(data["geometry"]))
    <Polygon object at 0x7fb3733d158e>
    
    0 回复  |  直到 6 年前
        1
  •  2
  •   tgrandje    4 年前

    你的解决方案似乎不像你想象的那么恶心。

    自从你 data['geometry'] 字段返回一个 WKT 字符串表示法( 'POLYGON ((-4.337076919429241 53.41842814531255, ... )) )你可以避免 fromstr 直接走过去 to a GEOSGeometry :

    from django.contrib.gis.geos import GEOSGeometry
    
    polygon = GEOSGeometry('POLYGON ((-4.337076919429241 53.41842814531255, ... ))')
    

    您还可以添加一些错误处理,不再担心解决方案崩溃:):

    for data in gdf.to_dict("records"):
        name = data.pop("name")
        geometry_str = data.pop('geometry')        
        try:
            geometry = GEOSGeometry(geometry_str)
        except (TypeError, ValueError) as exc:
            # If the geometry_str is not a valid WKT, EWKT or HEXEWKB string
            # or is None then either continue, break or do something else.
            # I will go with continue here.
            continue
    
        if geometry.geom_type != 'Polygon':
            # If the created geometry is not a Polygon don't pass it on MyModel
            continue 
    
        MyModel.objects.update_or_create(
            name=name, geometry=geometry,
            defaults=data,
        )