county.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. from sqlalchemy import Column, Integer, String, Text, Index, JSON
  2. from sqlalchemy.dialects.postgresql import JSONB
  3. from geoalchemy2 import Geometry
  4. from app.models.orm_models import Base
  5. from shapely.geometry import shape, MultiPolygon, Polygon
  6. import json
  7. class County(Base):
  8. """县级行政区划地理数据表"""
  9. __tablename__ = "counties"
  10. # 字段映射字典
  11. FIELD_MAPPING = {
  12. '县名': 'name',
  13. '县代码': 'code',
  14. '市名': 'city_name',
  15. '市代码': 'city_code',
  16. '省名': 'province_name',
  17. '省代码': 'province_code'
  18. }
  19. # 反向映射字典
  20. REVERSE_FIELD_MAPPING = {v: k for k, v in FIELD_MAPPING.items()}
  21. id = Column(Integer, primary_key=True, index=True)
  22. name = Column(String(100), nullable=False, comment="县名")
  23. code = Column(Integer, comment="县代码")
  24. city_name = Column(String(100), comment="市名")
  25. city_code = Column(Integer, comment="市代码")
  26. province_name = Column(String(100), comment="省名")
  27. province_code = Column(Integer, comment="省代码")
  28. # 使用PostGIS的几何类型来存储多边形数据
  29. geometry = Column(Geometry('MULTIPOLYGON', srid=4326), nullable=False, comment="县级行政区划的几何数据")
  30. # 存储完整的GeoJSON数据
  31. geojson = Column(JSON, nullable=False, comment="完整的GeoJSON数据")
  32. # 显式定义索引
  33. __table_args__ = (
  34. Index('idx_counties_name', 'name'),
  35. Index('idx_counties_code', 'code'),
  36. #Index('idx_counties_geometry', 'geometry', postgresql_using='gist'),
  37. )
  38. @classmethod
  39. def from_geojson_feature(cls, feature):
  40. """从GeoJSON Feature创建County实例
  41. Args:
  42. feature: GeoJSON Feature对象
  43. Returns:
  44. County: 新创建的County实例
  45. """
  46. properties = feature['properties']
  47. # 转换中文字段名为英文
  48. mapped_properties = {
  49. cls.FIELD_MAPPING.get(k, k): v
  50. for k, v in properties.items()
  51. }
  52. # 将GeoJSON geometry转换为EWKT格式(SRID=4326)
  53. geometry = feature['geometry']
  54. geom = shape(geometry)
  55. # 统一为 MultiPolygon 以匹配列类型
  56. if isinstance(geom, Polygon):
  57. geom = MultiPolygon([geom])
  58. wkt = f"SRID=4326;{geom.wkt}"
  59. # 创建实例
  60. county = cls(
  61. **mapped_properties,
  62. geometry=wkt,
  63. geojson=feature
  64. )
  65. return county
  66. def to_geojson_feature(self):
  67. """将County实例转换为GeoJSON Feature
  68. Returns:
  69. dict: GeoJSON Feature对象
  70. """
  71. properties = {}
  72. # 转换英文字段名为中文
  73. for eng_field, cn_field in self.REVERSE_FIELD_MAPPING.items():
  74. if hasattr(self, eng_field):
  75. properties[cn_field] = getattr(self, eng_field)
  76. return {
  77. 'type': 'Feature',
  78. 'properties': properties,
  79. 'geometry': self.geometry
  80. }