使用 SQLAlchemy Marshmallow 将 PostGIS POINT 转换为 Lat/Lon 值

问题描述

我使用带有 PostGIS 扩展的 Postgresql 13 在表 foos 中存储一些包含点坐标的数据。在 Python 3 方面,sqlAlchemy、geoalchemy2 和 marshmallow 被用于插入和选择这些数据。

当我们从该表中选择具有名为 POINTcoordinates 字段的行时,使用 Marshmallow 模式转储它会将 coordinates 显示为类似 0101000000137c889e81ef594024dc0a0c9854f53f 的字符串而不是POINT (103.742286332403 1.33315281585761),或者甚至更好,将其拆分为 2 个新值 latlon

目前:

row = db_session().query(Foo).first()
print(schema.dump(row))

# {'coordinates': '0101000000137c889e81ef594024dc0a0c9854f53f','id': 1,'name': 'foo'}

是否可以修改代码schema.dump(row)自动0101000000137c889e81ef594024dc0a0c9854f53f转换为POINT (103.742286332403 1.33315281585761)

期望:

row = db_session().query(Foo).first()
print(schema.dump(row))

# {'coordinates': 'POINT (103.742286332403 1.33315281585761)','name': 'foo'}

渴望(甚至更好!):

row = db_session().query(Foo).first()
print(schema.dump(row))

# {'lon': 103.742286332403,'lat': 1.33315281585761,'name': 'foo'}

谢谢!


test.py

from models.Foo import Foo,FooSchema
from utils.db import db_session
from geoalchemy2.shape import to_shape

if __name__ == '__main__':
    # Insert row into database
    schema = FooSchema(session=db_session)
    payload = {
        'name': 'foo','coordinates': f'POINT(103.742286332403 1.33315281585761)'
    }
    model = schema.load(payload)
    db_session.add(model)
    db_session.commit()

    # Retrieve row from database
    row = db_session().query(Foo).first()
    print(row)                          # <models.Foo.Foo object at 0x7fa3dc9d3c10>
    print(row.coordinates)              # 0101000000137c889e81ef594024dc0a0c9854f53f
    print(to_shape(row.coordinates))    # POINT (103.742286332403 1.33315281585761)

    data = schema.dump(row)
    print(data)                         # {'coordinates': '0101000000137c889e81ef594024dc0a0c9854f53f','name': 'foo'}

models/foo.py

from sqlalchemy import Column,String,Integer,Float
from sqlalchemy.types import ARRAY
from sqlalchemy.ext.declarative import declarative_base
from geoalchemy2 import Geometry
from marshmallow_sqlalchemy import sqlAlchemyAutoSchema
from marshmallow import fields
from marshmallow_sqlalchemy import ModelConverter


class GeoConverter(ModelConverter):
    sqlA_TYPE_MAPPING = ModelConverter.sqlA_TYPE_MAPPING.copy()
    sqlA_TYPE_MAPPING.update({
        Geometry: fields.Str
    })


Base = declarative_base()

class Foo(Base):
    __tablename__ = 'foos'
    id                      = Column(Integer,primary_key=True)
    name                    = Column(String())
    coordinates             = Column(Geometry('POINT'))


class FooSchema(sqlAlchemyAutoSchema):
    class Meta:
        model = Foo
        include_fk = True
        load_instance = True
        model_converter = GeoConverter

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)