Я использую Flask / SQLAlchemy для создания веб-приложения с картой в нем, поэтому, естественно, я использую базу данных PostGIS.Столбец geom требует ST_Transform и каким-то образом мне нужно превратить этот столбец и все остальные в JSON.Общая структура базы данных:
from app import login, db
from datetime import datetime
from geoalchemy2 import Geometry
from time import time
from flask import current_app
from sqlalchemy import func
class Streets(db.Model):
id = db.Column(db.Integer, primary_key=True)
street = db.Column(db.String(50))
geom = db.Column(Geometry(geometry_type='LINESTRING'))
def to_dict(self):
data = {
'id': self.id,
'street': self.street,
'_geom': func.ST_AsGeoJSON(func.ST_Transform(self.geom, 4326))
}
return data
Мой маршрут API превращает этот результат в API:
return jsonify(Streets.query.get_or_404(id).to_dict())
Но я продолжаю получать эту ошибку: NameError: name 'ST_AsGeoJSON' is not defined
Я также пытался создать свое значение _geom
следующим образом:
data['_geom'] = db.session.query(func.ST_AsGeoJSON(func.ST_Transform(self.geom, 4326)))
Сообщение об ошибке: TypeError: Object of type 'BaseQuery' is not JSON serializable
Наконец, я попытался APIмаршрут, как это:
data = Streets.to_dict(
db.session.query(
func.ST_AsGeoJSON(
func.ST_Transform(
Streets.geom, 4326
)
)
)
.filter(Streets.id==id))
return jsonify(data)
И я получаю другую ошибку: AttributeError: 'BaseQuery' object has no attribute 'id'
Если я запускаю это в flask shell
, это работает:
streets = db.session.query(
Streets.id,
Streets.street,
func.ST_AsGeoJSON(func.ST_Transform(Streets.geom, 4326)))
Какя могу выполнить ST_Transform
и получить JSON для моего API-маршрута?
ОБНОВЛЕНИЕ
Я нашел это в документации по SQLALchemy, которая дала мне некоторыеprogress: «orm.column_property () можно использовать для сопоставления выражения SQL».Поэтому я попытался добавить это к своему class Streets(db.Model)
:
coords = db.column_property(func.ST_AsGeoJSON(func.ST_Transform(geom, 4326)))
Затем я добавил это к data
следующим образом:
def to_dict(self):
data = {
'id': self.id,
'street': self.street,
'coords': self.coords
}
return data
Но теперь я дважды кодирую свои результаты,один раз в GeoJSON, а затем я jsonify
это:
return jsonify(Streets.query.get_or_404(id).to_dict())
Так что мой API вставляет \
s:
{"coords": "{\"type\":\"MultiLineString\",\"coordinates\":[[[-80.8357132798193,35.2260689001034],[-80.8347602582754,35.2252424284259]]]}"}
И использование ST_AsText
просто превращает его в текст:
{"coords": "MULTILINESTRING((-80.8357132798193 35.2260689001034,-80.8347602582754 35.2252424284259))"}
Я думаю, что я близок к этому обновлению, но есть ли у кого-нибудь предложение для получения правильного GeoJSON с JSON других полей моей базы данных?