python SQLAlchemy中的点类型?

fzwojiic  于 2023-09-29  发布在  Python
关注(0)|答案(4)|浏览(110)

我在Postgres中发现了关于Point类型的问题:http://www.postgresql.org/docs/current/interactive/datatype-geometric.html
有SQLAlchemy版本吗?
我以这种方式存储值:(40.721959482,-73.878993913)

xwbd5t1u

xwbd5t1u1#

你可以使用geoalchemy2 whis,它是sqlalchemy的扩展,也可以和flask-sqlalchemy一起使用。

from sqlalchemy import Column
from geoalchemy2 import Geometry
# and import others

class Shop(db.Model):
    # other fields
    coordinates = Column(Geometry('POINT'))
hmae6n7t

hmae6n7t2#

您可以扩展UserDefinedType以实现您想要的功能。
Here's an example I found非常接近您想要的UserDefinedType子类
请注意,Mohammad Amin's answer仅在您的点旨在成为地理点(纬度和经度约束)时才有效。如果你想表示平面上的任何一点,它就不适用了。此外,在这种情况下,您需要安装PostGIS扩展,如果您正在使用地理点,我建议您安装,因为它提供了大量的实用程序和额外的功能。

vxqlmq5t

vxqlmq5t3#

我发现这是穆罕默德的回答的一个小小的修改。
是的,我需要通过geo/sqlalchemy添加一个点列

from sqlalchemy import Column
from geoalchemy2 import Geometry
# and import others

class Shop(db.Model):
    # other fields
    coordinates = Column(Geometry('POINT'))

在我的PostGIS/Gres和PGloader端,因为我是从csv加载的,它将我的纬度和经度点格式化为:"(40.721959482, -73.878993913)"我需要在Vim中为我的所有条目(有很多)做一个宏,以强制该列遵循PostGIS中点的创建方式,所以我将csv列转换为point(40.721959482 -73.878993913),然后在创建表时将位置列的数据类型设置为geometry(point)location geometry(point)

jljoyd4f

jljoyd4f4#

下面是一个在SQLAlchemy中使用本地PostgreSQL点类型的工作示例,而不需要PostGIS或其他扩展,基于其他答案中的建议:

@dataclass(eq=True, frozen=True, slots=True)
class Coordinate:
    """
    Container to hold a geolocation.
    """

    lat: float
    lng: float

class LatLngType(sqlalchemy.types.UserDefinedType):
    """
    Custom SQLAlchemy type to handle POINT columns.

    References:

    - https://gist.github.com/kwatch/02b1a5a8899b67df2623
    - https://docs.sqlalchemy.org/en/14/core/custom_types.html#sqlalchemy.types.UserDefinedType  # noqa
    """

    # Can do because we made the Coordinate dataclass hashable.
    cache_ok = True

    def get_col_spec(self):
        return "POINT"

    def bind_expression(self, bindvalue):
        return func.POINT(bindvalue, type_=self)

    def bind_processor(self, dialect):
        """
        Return function to serialize a Coordinate into a database string literal.
        """

        def process(value: Coordinate | Tuple[float, float] | None) -> str | None:
            if value is None:
                return None

            if isinstance(value, tuple):
                value = Coordinate(*value)

            return f"({value.lat},{value.lng})"

        return process

    def result_processor(self, dialect, coltype):
        """
        Return function to parse a database string result into Python data type.
        """

        def process(value: str) -> Coordinate | None:
            if value is None:
                return None

            lat, lng = value.strip("()").split(",")

            return Coordinate(float(lat), float(lng))

        return process

如下所示:

class MyModel(Base):
    location = Column(LatLngType)

相关问题