5

我的问题是这个。我正在为一些数据创建一个模型。

class Cables(Base):
    __tablename__ = 'cables'

    id = Column(Integer, nullable=False)
    route = Column(Geometry(geometry_type='LINESTRING', srid=4326), nullable=False)

现在,我想将这样的路由转换为 GeoJSON。

我尝试过的事情

@app.route("/api/cable/<int:id>", methods=['GET'])
def get_cable(id):
    cable = session.query(Cables).filter(Cables.id == id).first()
    return str(geoalchemy2.functions.ST_AsGeoJSON(cable.route))

返回ST_AsGeoJSON(ST_GeomFromEWKB(:ST_GeomFromEWKB_1))

如果我更改退货:

return geoalchemy2.functions.ST_AsGeoJSON(cable.route)

返回TypeError: 'ST_AsGeoJSON' object is not callable

return str(cable.route)

返回0102000020e610000002000000b34fd4d9bca351c032e14d5134c240c0d24f8055e0a351c0dedea9f4dcbf40c0 这将表明我确实有一个几何对象。

return cable.route

返回TypeError: 'WKBElement' object is not callable

如果我打印路线类型,

print(type(cable.route))

返回

<class 'geoalchemy2.elements.WKBElement'>

我认为它应该返回此类的对象,而不是类本身。在这一点上我很困惑,我不知道我现在应该做什么。

有什么建议么?

4

3 回答 3

4

似乎调用 ST_AsGeoJSON 的正确方法是在查询中。例如,

ruta = session.query(Cables.route.ST_AsGeoJSON()).filter(Cables.id == id).first()

我最终做的是安装一个新库(匀称)以读取十六进制字节串,然后将其转换为字典,因为字典可以以简单的方式转换为 json。

def ewkb_route_to_dict(self):
    """
    returns the cable's route as a dictionary.
    It uses shapely.wkb.loads. The first argument is the route as a bytestring,
    and the second one (True) is to tell loads that
    the input wkb will be represented as a hex string
    """
    return mapping(shapely.wkb.loads(str(self.route), True))

然后在我的字符串方法中:

def __str__(self):
    d = dict()
    ...
    d["route"] = self.ewkb_route_to_dict()
    ...
    return dumps(d)

这将正确地将几何转换为 GeoJSON。

于 2017-01-18T15:37:38.083 回答
2

我知道这篇文章很旧,但对于那些仍然有这个困难的人来说,它遵循我的解决方案:

import ast
from flask.json import jsonify
from sqlalchemy import func

@app.route("/api/cable/<int:id>", methods=['GET'])
def get_cable(id):
    geom = session.query(func.ST_AsGeoJSON(Cables.route)).filter(Cables.id == id).scalar()
    # The code below makes a geojson with CRS.
    # See http://www.postgis.org/docs/ST_AsGeoJSON.html for more details.
    #geom = session.query(func.ST_AsGeoJSON(Cables.route,15,2)).filter(Cables.id == id).scalar()
    return jsonify(ast.literal_eval(geom))
于 2018-07-27T17:17:21.643 回答
1

在 docs中,PostGIS 有用地通知您:

ST_AsGeoJSON只构建几何。您需要自己从 Postgres 表中构建功能的其余部分

实际上,尝试将输出发送ST_AsGeoJSON到 Leaflet 层将失败,因为它不是有效的Feature. 虽然文档提供了 25 行 PostGIS 代码,但将其与 SQLAlchemy 一起使用并不吸引人。我发现最简单的方法是使用一个小的 python 库,shapely-geojson.

$ pip install shapely-geojson

然后在您的代码中:

from shapely_geojson import dumps, Feature
from geoalchemy2.shape import to_shape

cable = session.query(Cables).filter(Cables.id == id).first()
feature = Feature(to_shape(cable[0]))
geoJSON = dumps(feature)

请注意,GeoJSON 标准在 2016 年发生了变化,以强制执行右手规则。根据您的线或多边形在数据中的结构方式以及接收软件的挑剔程度,您可能需要使用它geojson_rewind来更改点的顺序。

于 2019-03-12T10:59:39.153 回答