update main file

This commit is contained in:
DmsAnhr 2025-12-22 15:24:15 +07:00
parent 1b7f6ab5ea
commit b4fa7e123b

130
main.py
View File

@ -10,7 +10,9 @@ from qgis.core import (
QgsVectorLayerExporter, QgsVectorLayerExporter,
QgsDataSourceUri, QgsDataSourceUri,
QgsProviderRegistry, QgsProviderRegistry,
QgsCoordinateReferenceSystem QgsCoordinateReferenceSystem,
QgsWkbTypes,
QgsGeometry
) )
from qgis.PyQt.QtCore import QByteArray from qgis.PyQt.QtCore import QByteArray
from config import HOST,PORT,DB,USER,PWD,SCHEMA,GEOM_COL from config import HOST,PORT,DB,USER,PWD,SCHEMA,GEOM_COL
@ -43,17 +45,38 @@ def clean_table(table_name: str):
} }
from pydantic import BaseModel
@app.post("/process/{table_name}") class ProcessRequest(BaseModel):
def process_table(table_name: str, background: BackgroundTasks): table_name: str
job_id = uuid4().hex job_id: str
background.add_task(run_clean_table, table_name, job_id)
@app.post("/process")
def process_table(
payload: ProcessRequest,
background: BackgroundTasks
):
background.add_task(
run_clean_table,
payload.table_name,
payload.job_id
)
return { return {
"status": "ACCEPTED", "status": "ACCEPTED",
"job_id": job_id, "job_id": payload.job_id,
"table": table_name "table": payload.table_name
} }
# @app.post("/process/{table_name}")
# def process_table(table_name: str, background: BackgroundTasks):
# job_id = uuid4().hex
# background.add_task(run_clean_table, table_name, job_id)
# return {
# "status": "ACCEPTED",
# "job_id": job_id,
# "table": table_name
# }
def run_clean_table(table_name: str, job_id: str): def run_clean_table(table_name: str, job_id: str):
@ -80,7 +103,7 @@ def run_clean_table(table_name: str, job_id: str):
} }
requests.post( requests.post(
"http://localhost:8000/jobs/callback", "http://localhost:8000/dataset/jobs/callback",
json=callback_payload json=callback_payload
) )
@ -102,6 +125,81 @@ def to_python(v):
# Fallback # Fallback
return v return v
# def get_postgis_geom_type(layer):
# for f in layer.getFeatures():
# g = f.geometry()
# if g.isMultipart():
# return QgsWkbTypes.displayString(g.wkbType()).upper()
# else:
# base = QgsWkbTypes.displayString(g.wkbType()).upper()
# if "POINT" in base:
# return "MULTIPOINT"
# if "LINESTRING" in base:
# return "MULTILINESTRING"
# if "POLYGON" in base:
# return "MULTIPOLYGON"
# return "GEOMETRY"
def get_postgis_geom_type(layer):
has_z = False
has_m = False
base_type = None # polygon / linestring / point
is_multi = False
for f in layer.getFeatures():
g = f.geometry()
if g.isEmpty():
continue
wkb = g.wkbType()
# Detect Z & M
if QgsWkbTypes.hasZ(wkb):
has_z = True
if QgsWkbTypes.hasM(wkb):
has_m = True
# Detect MULTI
if QgsWkbTypes.isMultiType(wkb):
is_multi = True
# Detect base type (polygon / line / point)
geom_type = QgsWkbTypes.geometryType(wkb)
base_type = geom_type # polygon=2, line=1, point=0
if base_type is None:
return "GEOMETRY"
# Convert base_type to PostGIS string
if base_type == QgsWkbTypes.PointGeometry:
base = "POINT"
elif base_type == QgsWkbTypes.LineGeometry:
base = "LINESTRING"
elif base_type == QgsWkbTypes.PolygonGeometry:
base = "POLYGON"
else:
base = "GEOMETRY"
# Force MULTI
if base != "GEOMETRY":
base = "MULTI" + base
# Add dimensionality
if has_z and has_m:
base += "ZM"
elif has_z:
base += "Z"
elif has_m:
base += "M"
return base
def save_to_postgis(layer, table_name): def save_to_postgis(layer, table_name):
host = HOST host = HOST
port = PORT port = PORT
@ -126,14 +224,13 @@ def save_to_postgis(layer, table_name):
# DROP TABLE # DROP TABLE
cur.execute(f'DROP TABLE IF EXISTS "{schema}"."{table_name}" CASCADE') cur.execute(f'DROP TABLE IF EXISTS "{schema}"."{table_name}" CASCADE')
print(f'Drop table {table_name}')
# CREATE TABLE
field_defs = [] field_defs = []
for f in fields: for f in fields:
if f.name() == geom_col: if f.name() == geom_col:
continue continue
# type mapping
t = f.typeName().lower() t = f.typeName().lower()
if "int" in t: if "int" in t:
pg_type = "INTEGER" pg_type = "INTEGER"
@ -145,12 +242,15 @@ def save_to_postgis(layer, table_name):
col = f.name().replace(" ", "_") col = f.name().replace(" ", "_")
field_defs.append(f'"{col}" {pg_type}') field_defs.append(f'"{col}" {pg_type}')
# geometry column # AUTODETECT 2D/3D geometry
field_defs.append(f'"{geom_col}" geometry(MultiPolygon,{srid})') pg_geom_type = get_postgis_geom_type(layer)
print("get type")
field_defs.append(f'"{geom_col}" geometry({pg_geom_type},{srid})')
create_sql = f'CREATE TABLE "{schema}"."{table_name}" ({",".join(field_defs)});' create_sql = f'CREATE TABLE "{schema}"."{table_name}" ({",".join(field_defs)});'
cur.execute(create_sql) cur.execute(create_sql)
# Prepare INSERT # Prepare INSERT
attribute_columns = [ attribute_columns = [
f'"{f.name().replace(" ", "_")}"' f'"{f.name().replace(" ", "_")}"'
@ -177,6 +277,8 @@ def save_to_postgis(layer, table_name):
geom = feat.geometry() geom = feat.geometry()
wkb_bytes = geom.asWkb() wkb_bytes = geom.asWkb()
# geom_2d = QgsGeometry.fromWkt(geom.asWkt())
# wkb_bytes = geom_2d.asWkb()
if isinstance(wkb_bytes, QByteArray): if isinstance(wkb_bytes, QByteArray):
wkb_bytes = bytes(wkb_bytes) wkb_bytes = bytes(wkb_bytes)
@ -190,5 +292,3 @@ def save_to_postgis(layer, table_name):
print(f"[DB] Inserted features: {count}") print(f"[DB] Inserted features: {count}")