正在显示
17 个修改的文件
包含
1390 行增加
和
220 行删除
| @@ -8,15 +8,17 @@ from app.models import Database,db,DES,Table,Columns,TableVacuate | @@ -8,15 +8,17 @@ from app.models import Database,db,DES,Table,Columns,TableVacuate | ||
| 8 | import uuid | 8 | import uuid |
| 9 | from . import database_test | 9 | from . import database_test |
| 10 | # from app.util import open_pg_data_source | 10 | # from app.util import open_pg_data_source |
| 11 | -from osgeo.ogr import DataSource,Layer,FeatureDefn,FieldDefn,Feature | 11 | +from osgeo.ogr import DataSource,Layer,FeatureDefn,FieldDefn,Feature,Geometry |
| 12 | from sqlalchemy.orm import Session | 12 | from sqlalchemy.orm import Session |
| 13 | from sqlalchemy import create_engine | 13 | from sqlalchemy import create_engine |
| 14 | from sqlalchemy.orm import sessionmaker | 14 | from sqlalchemy.orm import sessionmaker |
| 15 | from app.util.component.ApiTemplate import ApiTemplate | 15 | from app.util.component.ApiTemplate import ApiTemplate |
| 16 | from app.util.component.PGUtil import PGUtil | 16 | from app.util.component.PGUtil import PGUtil |
| 17 | +from app.util.component.SQLUtil import SQLUtil | ||
| 17 | from app.util.component.GeometryAdapter import GeometryAdapter | 18 | from app.util.component.GeometryAdapter import GeometryAdapter |
| 19 | +from app.util.component.StructuredPrint import StructurePrint | ||
| 18 | class Api(ApiTemplate): | 20 | class Api(ApiTemplate): |
| 19 | - api_name = "数据库注册" | 21 | + api_name = "注册数据库" |
| 20 | def process(self): | 22 | def process(self): |
| 21 | res ={} | 23 | res ={} |
| 22 | res["result"] = False | 24 | res["result"] = False |
| @@ -29,7 +31,7 @@ class Api(ApiTemplate): | @@ -29,7 +31,7 @@ class Api(ApiTemplate): | ||
| 29 | encryption = int(self.para.get("encryption","0")) | 31 | encryption = int(self.para.get("encryption","0")) |
| 30 | if encryption: | 32 | if encryption: |
| 31 | passwd = DES.decode(passwd) | 33 | passwd = DES.decode(passwd) |
| 32 | - | 34 | + |
| 33 | sqlalchemy_uri = "postgresql://{}:{}@{}:{}/{}".format(user,passwd,host,port,database) | 35 | sqlalchemy_uri = "postgresql://{}:{}@{}:{}/{}".format(user,passwd,host,port,database) |
| 34 | connectsrt = "hostaddr={} port={} dbname='{}' user='{}' password='{}'".format(host,port,database,user,passwd) | 36 | connectsrt = "hostaddr={} port={} dbname='{}' user='{}' password='{}'".format(host,port,database,user,passwd) |
| 35 | 37 | ||
| @@ -87,26 +89,29 @@ class Api(ApiTemplate): | @@ -87,26 +89,29 @@ class Api(ApiTemplate): | ||
| 87 | 89 | ||
| 88 | def register_table(self,database): | 90 | def register_table(self,database): |
| 89 | this_time = datetime.datetime.now() | 91 | this_time = datetime.datetime.now() |
| 92 | + | ||
| 90 | pg_ds: DataSource = PGUtil.open_pg_data_source(1, DES.decode(database.sqlalchemy_uri)) | 93 | pg_ds: DataSource = PGUtil.open_pg_data_source(1, DES.decode(database.sqlalchemy_uri)) |
| 94 | + db_tuple = PGUtil.get_info_from_sqlachemy_uri(DES.decode(database.sqlalchemy_uri)) | ||
| 91 | 95 | ||
| 92 | # 注册空间表 | 96 | # 注册空间表 |
| 93 | - spatial_table_name,tables = self.register_spatial_table(pg_ds, database, this_time) | 97 | + spatial_table_name,tables = self.register_spatial_table(pg_ds, database, this_time,db_tuple) |
| 94 | 98 | ||
| 95 | #注册抽稀表 | 99 | #注册抽稀表 |
| 96 | - self.regiser_vacuate_talbe(pg_ds,tables) | 100 | + self.regiser_vacuate_table(pg_ds,tables,db_tuple) |
| 97 | 101 | ||
| 98 | #注册普通表 | 102 | #注册普通表 |
| 99 | - self.register_common_table(this_time,database,spatial_table_name) | 103 | + self.register_common_table(this_time,database,spatial_table_name,db_tuple) |
| 100 | 104 | ||
| 101 | pg_ds.Destroy() | 105 | pg_ds.Destroy() |
| 102 | 106 | ||
| 103 | 107 | ||
| 104 | - def register_spatial_table(self,pg_ds,database,this_time): | 108 | + def register_spatial_table(self,pg_ds,database,this_time,db_tuple): |
| 105 | spatial_table_name =[] | 109 | spatial_table_name =[] |
| 106 | tables=[] | 110 | tables=[] |
| 107 | for i in range(pg_ds.GetLayerCount()): | 111 | for i in range(pg_ds.GetLayerCount()): |
| 108 | layer: Layer = pg_ds.GetLayer(i) | 112 | layer: Layer = pg_ds.GetLayer(i) |
| 109 | l_name = layer.GetName() | 113 | l_name = layer.GetName() |
| 114 | + | ||
| 110 | # 只注册public的空间表,其他表空间的表名会有. | 115 | # 只注册public的空间表,其他表空间的表名会有. |
| 111 | if layer.GetName().__contains__("."): | 116 | if layer.GetName().__contains__("."): |
| 112 | continue | 117 | continue |
| @@ -116,9 +121,15 @@ class Api(ApiTemplate): | @@ -116,9 +121,15 @@ class Api(ApiTemplate): | ||
| 116 | spatial_table_name.append(layer.GetName()) | 121 | spatial_table_name.append(layer.GetName()) |
| 117 | continue | 122 | continue |
| 118 | 123 | ||
| 124 | + # 没有权限的表跳过 | ||
| 125 | + if not PGUtil.check_table_privilege(l_name,"SELECT",db_tuple[0],pg_ds): | ||
| 126 | + StructurePrint.print("用户{}对表{}没有select权限!".format(db_tuple[0],l_name),"warn") | ||
| 127 | + continue | ||
| 128 | + | ||
| 119 | # 范围统计和数量统计以100w为界限 | 129 | # 范围统计和数量统计以100w为界限 |
| 120 | query_count_layer: Layer = pg_ds.ExecuteSQL( | 130 | query_count_layer: Layer = pg_ds.ExecuteSQL( |
| 121 | '''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format(l_name)) | 131 | '''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format(l_name)) |
| 132 | + | ||
| 122 | feature_count = query_count_layer.GetFeature(0).GetField("ec") | 133 | feature_count = query_count_layer.GetFeature(0).GetField("ec") |
| 123 | # 要素少于100w可以精确统计 | 134 | # 要素少于100w可以精确统计 |
| 124 | if feature_count < 1000000: | 135 | if feature_count < 1000000: |
| @@ -137,11 +148,13 @@ class Api(ApiTemplate): | @@ -137,11 +148,13 @@ class Api(ApiTemplate): | ||
| 137 | 148 | ||
| 138 | table_guid = uuid.uuid1().__str__() | 149 | table_guid = uuid.uuid1().__str__() |
| 139 | 150 | ||
| 151 | + geom_type = GeometryAdapter.get_geometry_type(layer) | ||
| 152 | + | ||
| 140 | table = Table(guid=table_guid, | 153 | table = Table(guid=table_guid, |
| 141 | database_guid=database.guid, | 154 | database_guid=database.guid, |
| 142 | # alias=layer.GetName(), | 155 | # alias=layer.GetName(), |
| 143 | name=layer.GetName(), create_time=this_time, update_time=this_time, | 156 | name=layer.GetName(), create_time=this_time, update_time=this_time, |
| 144 | - table_type=GeometryAdapter.get_table_type(GeometryAdapter.get_geometry_type(layer)), | 157 | + table_type=GeometryAdapter.get_table_type(geom_type), |
| 145 | extent=extent, | 158 | extent=extent, |
| 146 | feature_count=feature_count | 159 | feature_count=feature_count |
| 147 | ) | 160 | ) |
| @@ -164,19 +177,26 @@ class Api(ApiTemplate): | @@ -164,19 +177,26 @@ class Api(ApiTemplate): | ||
| 164 | return spatial_table_name,tables | 177 | return spatial_table_name,tables |
| 165 | 178 | ||
| 166 | 179 | ||
| 167 | - def register_common_table(self,this_time,database,spatial_table_name): | 180 | + def register_common_table(self,this_time,database,spatial_table_name,db_tuple): |
| 168 | # 注册普通表 | 181 | # 注册普通表 |
| 169 | db_session: Session = PGUtil.get_db_session(DES.decode(database.sqlalchemy_uri)) | 182 | db_session: Session = PGUtil.get_db_session(DES.decode(database.sqlalchemy_uri)) |
| 170 | 183 | ||
| 171 | # 只注册public中的表 | 184 | # 只注册public中的表 |
| 172 | result = db_session.execute( | 185 | result = db_session.execute( |
| 173 | "select relname as tabname from pg_class c where relkind = 'r' and relnamespace=2200 and relname not like 'pg_%' and relname not like 'sql_%' order by relname").fetchall() | 186 | "select relname as tabname from pg_class c where relkind = 'r' and relnamespace=2200 and relname not like 'pg_%' and relname not like 'sql_%' order by relname").fetchall() |
| 187 | + | ||
| 174 | for re in result: | 188 | for re in result: |
| 175 | table_name = re[0] | 189 | table_name = re[0] |
| 176 | if table_name not in spatial_table_name: | 190 | if table_name not in spatial_table_name: |
| 177 | 191 | ||
| 192 | + # 没有权限的表跳过 | ||
| 193 | + if not SQLUtil.check_table_privilege(table_name, "SELECT", db_tuple[0], db_session): | ||
| 194 | + StructurePrint.print("用户{}对表{}没有select权限!".format(db_tuple[0],table_name), "warn") | ||
| 195 | + continue | ||
| 196 | + | ||
| 178 | table_guid = uuid.uuid1().__str__() | 197 | table_guid = uuid.uuid1().__str__() |
| 179 | - count = db_session.execute('select count(*) from "{}"'.format(table_name)).fetchone()[0] | 198 | + |
| 199 | + count = SQLUtil.get_table_count(table_name,db_session) | ||
| 180 | 200 | ||
| 181 | table = Table(guid=table_guid, | 201 | table = Table(guid=table_guid, |
| 182 | database_guid=database.guid, | 202 | database_guid=database.guid, |
| @@ -209,15 +229,26 @@ class Api(ApiTemplate): | @@ -209,15 +229,26 @@ class Api(ApiTemplate): | ||
| 209 | column = Columns(guid=uuid.uuid1().__str__(), table_guid=table_guid, | 229 | column = Columns(guid=uuid.uuid1().__str__(), table_guid=table_guid, |
| 210 | name=col[1], create_time=this_time, update_time=this_time) | 230 | name=col[1], create_time=this_time, update_time=this_time) |
| 211 | db.session.add(column) | 231 | db.session.add(column) |
| 232 | + db_session.commit() | ||
| 212 | db_session.close() | 233 | db_session.close() |
| 213 | 234 | ||
| 214 | - def regiser_vacuate_talbe(self,pg_ds,tables): | 235 | + |
| 236 | + def regiser_vacuate_table(self,pg_ds,tables,db_tuple): | ||
| 215 | 237 | ||
| 216 | # 注册抽稀表 | 238 | # 注册抽稀表 |
| 217 | for i in range(pg_ds.GetLayerCount()): | 239 | for i in range(pg_ds.GetLayerCount()): |
| 218 | layer:Layer = pg_ds.GetLayer(i) | 240 | layer:Layer = pg_ds.GetLayer(i) |
| 219 | l_name = layer.GetName() | 241 | l_name = layer.GetName() |
| 242 | + | ||
| 243 | + | ||
| 244 | + | ||
| 220 | if l_name.__contains__("_vacuate_"): | 245 | if l_name.__contains__("_vacuate_"): |
| 246 | + | ||
| 247 | + # 没有权限的表跳过 | ||
| 248 | + if not PGUtil.check_table_privilege(l_name, "SELECT", db_tuple[0], pg_ds): | ||
| 249 | + StructurePrint.print("用户{}对表{}没有select权限!".format(db_tuple[0], l_name), "warn") | ||
| 250 | + continue | ||
| 251 | + | ||
| 221 | base_layer_name=l_name.split("_vacuate_")[0] | 252 | base_layer_name=l_name.split("_vacuate_")[0] |
| 222 | level = l_name.split("_")[-2] | 253 | level = l_name.split("_")[-2] |
| 223 | pixel_distance_str: str ="0" | 254 | pixel_distance_str: str ="0" |
| @@ -227,15 +258,17 @@ class Api(ApiTemplate): | @@ -227,15 +258,17 @@ class Api(ApiTemplate): | ||
| 227 | pixel_distance_str="0.{}".format(pixel_distance_str) | 258 | pixel_distance_str="0.{}".format(pixel_distance_str) |
| 228 | except: | 259 | except: |
| 229 | pass | 260 | pass |
| 230 | - base_table = [table for table in tables if table.name.__eq__(base_layer_name)][0] | ||
| 231 | - table_vacuate = TableVacuate(guid=uuid.uuid1().__str__(), | ||
| 232 | - table_guid=base_table.guid, | ||
| 233 | - level=level, | ||
| 234 | - name=l_name, | ||
| 235 | - pixel_distance=float(pixel_distance_str)) | 261 | + base_table = [table for table in tables if table.name.__eq__(base_layer_name)] |
| 262 | + if base_table: | ||
| 263 | + base_table = base_table[0] | ||
| 264 | + table_vacuate = TableVacuate(guid=uuid.uuid1().__str__(), | ||
| 265 | + table_guid=base_table.guid, | ||
| 266 | + level=level, | ||
| 267 | + name=l_name, | ||
| 268 | + pixel_distance=float(pixel_distance_str)) | ||
| 236 | 269 | ||
| 237 | - Table.query.filter_by(guid=base_table.guid).update({"is_vacuate": 1}) | ||
| 238 | - db.session.add(table_vacuate) | 270 | + Table.query.filter_by(guid=base_table.guid).update({"is_vacuate":1}) |
| 271 | + db.session.add(table_vacuate) | ||
| 239 | 272 | ||
| 240 | 273 | ||
| 241 | 274 | ||
| @@ -247,7 +280,6 @@ class Api(ApiTemplate): | @@ -247,7 +280,6 @@ class Api(ApiTemplate): | ||
| 247 | engine = create_engine(sqlachemy_uri) | 280 | engine = create_engine(sqlachemy_uri) |
| 248 | system_session = sessionmaker(bind=engine)() | 281 | system_session = sessionmaker(bind=engine)() |
| 249 | system_session.execute(test_sql).fetchone() | 282 | system_session.execute(test_sql).fetchone() |
| 250 | - | ||
| 251 | except: | 283 | except: |
| 252 | check = False | 284 | check = False |
| 253 | finally: | 285 | finally: |
| @@ -281,10 +313,6 @@ class Api(ApiTemplate): | @@ -281,10 +313,6 @@ class Api(ApiTemplate): | ||
| 281 | {"name": "alias", | 313 | {"name": "alias", |
| 282 | "in": "formData", | 314 | "in": "formData", |
| 283 | "type": "string","description":"数据库别名","required": "true"}, | 315 | "type": "string","description":"数据库别名","required": "true"}, |
| 284 | - | ||
| 285 | - {"name": "encryption", | ||
| 286 | - "in": "formData", | ||
| 287 | - "type": "integer", "description": "密码是否加密", "enum": [0,1]}, | ||
| 288 | ], | 316 | ], |
| 289 | "responses":{ | 317 | "responses":{ |
| 290 | 200:{ | 318 | 200:{ |
| @@ -8,28 +8,28 @@ from app.models import * | @@ -8,28 +8,28 @@ from app.models import * | ||
| 8 | 8 | ||
| 9 | import traceback | 9 | import traceback |
| 10 | 10 | ||
| 11 | -from osgeo.ogr import DataSource,Layer,FeatureDefn,FieldDefn | ||
| 12 | -from osgeo import gdal ,ogr | 11 | +from osgeo.ogr import DataSource,Layer,FeatureDefn,FieldDefn,Feature |
| 12 | +from osgeo import gdal,ogr | ||
| 13 | import os | 13 | import os |
| 14 | import uuid | 14 | import uuid |
| 15 | import configure | 15 | import configure |
| 16 | from app.util.component.ApiTemplate import ApiTemplate | 16 | from app.util.component.ApiTemplate import ApiTemplate |
| 17 | from app.util.component.PGUtil import PGUtil | 17 | from app.util.component.PGUtil import PGUtil |
| 18 | from app.util.component.ZipUtil import ZipUtil | 18 | from app.util.component.ZipUtil import ZipUtil |
| 19 | + | ||
| 19 | class Api(ApiTemplate): | 20 | class Api(ApiTemplate): |
| 20 | 21 | ||
| 21 | - api_name = "下载数据" | ||
| 22 | def process(self): | 22 | def process(self): |
| 23 | #获取参数 | 23 | #获取参数 |
| 24 | 24 | ||
| 25 | #返回结果 | 25 | #返回结果 |
| 26 | - res={} | 26 | + result={} |
| 27 | #设置编码 | 27 | #设置编码 |
| 28 | encoding = self.para.get("encoding") | 28 | encoding = self.para.get("encoding") |
| 29 | if encoding: | 29 | if encoding: |
| 30 | gdal.SetConfigOption("SHAPE_ENCODING",encoding) | 30 | gdal.SetConfigOption("SHAPE_ENCODING",encoding) |
| 31 | else: | 31 | else: |
| 32 | - gdal.SetConfigOption("SHAPE_ENCODING", "GBK") | 32 | + gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8") |
| 33 | 33 | ||
| 34 | ds:DataSource = None | 34 | ds:DataSource = None |
| 35 | try: | 35 | try: |
| @@ -38,6 +38,7 @@ class Api(ApiTemplate): | @@ -38,6 +38,7 @@ class Api(ApiTemplate): | ||
| 38 | database = Database.query.filter_by(guid=database_guid).one_or_none() | 38 | database = Database.query.filter_by(guid=database_guid).one_or_none() |
| 39 | if not database: | 39 | if not database: |
| 40 | raise Exception("数据库不存在!") | 40 | raise Exception("数据库不存在!") |
| 41 | + | ||
| 41 | 42 | ||
| 42 | ds:DataSource = PGUtil.open_pg_data_source(0,DES.decode(database.sqlalchemy_uri)) | 43 | ds:DataSource = PGUtil.open_pg_data_source(0,DES.decode(database.sqlalchemy_uri)) |
| 43 | 44 | ||
| @@ -49,16 +50,16 @@ class Api(ApiTemplate): | @@ -49,16 +50,16 @@ class Api(ApiTemplate): | ||
| 49 | if download_type.__eq__("gdb"): | 50 | if download_type.__eq__("gdb"): |
| 50 | data = self.download_gdb(table_names, ds,database_guid) | 51 | data = self.download_gdb(table_names, ds,database_guid) |
| 51 | 52 | ||
| 52 | - res["data"] = data | ||
| 53 | - res["result"] = True | 53 | + result["data"] = data |
| 54 | + result["state"] = 1 | ||
| 54 | except Exception as e: | 55 | except Exception as e: |
| 55 | print(traceback.format_exc()) | 56 | print(traceback.format_exc()) |
| 56 | - res["msg"]= e.__str__() | ||
| 57 | - res["result"]=False | 57 | + result["message"]= e.__str__() |
| 58 | + result["state"]=-1 | ||
| 58 | finally: | 59 | finally: |
| 59 | if ds: | 60 | if ds: |
| 60 | ds.Destroy() | 61 | ds.Destroy() |
| 61 | - return res | 62 | + return result |
| 62 | 63 | ||
| 63 | 64 | ||
| 64 | def download_shp(self,table_names,ds): | 65 | def download_shp(self,table_names,ds): |
| @@ -77,9 +78,23 @@ class Api(ApiTemplate): | @@ -77,9 +78,23 @@ class Api(ApiTemplate): | ||
| 77 | dirpath = os.path.join(parent, "file_tmp", uuid_) | 78 | dirpath = os.path.join(parent, "file_tmp", uuid_) |
| 78 | os.makedirs(dirpath) | 79 | os.makedirs(dirpath) |
| 79 | data_source: DataSource = driver.CreateDataSource(dirpath + "/{}.shp".format(table_name)) | 80 | data_source: DataSource = driver.CreateDataSource(dirpath + "/{}.shp".format(table_name)) |
| 80 | - data_source.CopyLayer(layer, table_name) | 81 | + # data_source.CopyLayer(layer, table_name) |
| 82 | + | ||
| 83 | + | ||
| 84 | + fid = layer.GetFIDColumn() | ||
| 85 | + pg_layer: Layer = data_source.CreateLayer(table_name, layer.GetSpatialRef(), layer.GetGeomType()) | ||
| 86 | + schema = [sche for sche in layer.schema if not sche.name.__eq__(fid)] | ||
| 87 | + | ||
| 88 | + pg_layer.CreateFields(schema) | ||
| 89 | + layer.ResetReading() | ||
| 90 | + for feature in layer: | ||
| 91 | + pg_layer.CreateFeature(feature) | ||
| 92 | + | ||
| 81 | data_source.Destroy() | 93 | data_source.Destroy() |
| 94 | + | ||
| 95 | + | ||
| 82 | ZipUtil.create_zip(os.path.join(parent, "file_tmp", table_name+"_"+uuid_) + ".zip", [dirpath]) | 96 | ZipUtil.create_zip(os.path.join(parent, "file_tmp", table_name+"_"+uuid_) + ".zip", [dirpath]) |
| 97 | + | ||
| 83 | return "http://" + configure.deploy_ip_host + "/API/IO/Download/{}".format(table_name+"_"+uuid_ + ".zip") | 98 | return "http://" + configure.deploy_ip_host + "/API/IO/Download/{}".format(table_name+"_"+uuid_ + ".zip") |
| 84 | 99 | ||
| 85 | 100 | ||
| @@ -114,13 +129,32 @@ class Api(ApiTemplate): | @@ -114,13 +129,32 @@ class Api(ApiTemplate): | ||
| 114 | # if not table_alias: | 129 | # if not table_alias: |
| 115 | # table_alias = table_name | 130 | # table_alias = table_name |
| 116 | # table_name = "table{}".format(table_name.__hash__()) | 131 | # table_name = "table{}".format(table_name.__hash__()) |
| 117 | - | ||
| 118 | - gdb_ds.CopyLayer(layer, table_name,["LAYER_ALIAS={}".format(table_alias)]) | 132 | + |
| 133 | + fid = layer.GetFIDColumn() | ||
| 134 | + pg_layer: Layer = gdb_ds.CreateLayer(table_name, layer.GetSpatialRef(), layer.GetGeomType(),["LAYER_ALIAS={}".format(table_alias)]) | ||
| 135 | + schema = [sche for sche in layer.schema if not sche.name.__eq__(fid)] | ||
| 136 | + # schema = layer.schema | ||
| 137 | + pg_layer.CreateFields(schema) | ||
| 138 | + | ||
| 139 | + | ||
| 140 | + # gdb 不支持fid=0的要素,所以识别到后要+1 | ||
| 141 | + offset = 0 | ||
| 142 | + f1:Feature = layer.GetNextFeature() | ||
| 143 | + if f1: | ||
| 144 | + if f1.GetFID().__eq__(0): | ||
| 145 | + offset = 1 | ||
| 146 | + layer.ResetReading() | ||
| 147 | + for feature in layer: | ||
| 148 | + feature.SetFID(feature.GetFID()+offset) | ||
| 149 | + pg_layer.CreateFeature(feature) | ||
| 150 | + | ||
| 151 | + | ||
| 152 | + # gdb_ds.CopyLayer(layer, table_name,["LAYER_ALIAS={}".format(table_alias)]) | ||
| 119 | 153 | ||
| 120 | gdb_ds.Destroy() | 154 | gdb_ds.Destroy() |
| 121 | ZipUtil.create_zip(gdb_path + ".zip", [gdb_path]) | 155 | ZipUtil.create_zip(gdb_path + ".zip", [gdb_path]) |
| 122 | data.append({"name": ",".join(table_names), "download_url": "http://" + configure.deploy_ip_host + "/API/IO/Download/{}".format(uuid_+".gdb" + ".zip")}) | 156 | data.append({"name": ",".join(table_names), "download_url": "http://" + configure.deploy_ip_host + "/API/IO/Download/{}".format(uuid_+".gdb" + ".zip")}) |
| 123 | - | 157 | + |
| 124 | 158 | ||
| 125 | return data | 159 | return data |
| 126 | 160 |
| @@ -18,6 +18,10 @@ from . import table_refresh | @@ -18,6 +18,10 @@ from . import table_refresh | ||
| 18 | from . import table_delete | 18 | from . import table_delete |
| 19 | from . import table_view | 19 | from . import table_view |
| 20 | from . import table_vacuate | 20 | from . import table_vacuate |
| 21 | +from . import table_vacuate_one | ||
| 22 | +from . import table_vacuate_info | ||
| 23 | +from . import table_vacuate_ref | ||
| 24 | +from . import table_vacuate_delete | ||
| 21 | class DataManager(BlueprintApi): | 25 | class DataManager(BlueprintApi): |
| 22 | 26 | ||
| 23 | bp = Blueprint("DataManager", __name__, url_prefix="/API/Manager") | 27 | bp = Blueprint("DataManager", __name__, url_prefix="/API/Manager") |
| @@ -106,4 +110,41 @@ class DataManager(BlueprintApi): | @@ -106,4 +110,41 @@ class DataManager(BlueprintApi): | ||
| 106 | """ | 110 | """ |
| 107 | 数据抽稀 | 111 | 数据抽稀 |
| 108 | """ | 112 | """ |
| 109 | - return table_vacuate.Api().result | ||
| 113 | + return table_vacuate.Api().result | ||
| 114 | + | ||
| 115 | + @staticmethod | ||
| 116 | + @bp.route('/TableVacuateOne', methods=['POST']) | ||
| 117 | + @swag_from(table_vacuate_one.Api.api_doc) | ||
| 118 | + def api_table_vacuate_one(): | ||
| 119 | + """ | ||
| 120 | + 单独数据抽稀 | ||
| 121 | + """ | ||
| 122 | + return table_vacuate_one.Api().result | ||
| 123 | + | ||
| 124 | + | ||
| 125 | + @staticmethod | ||
| 126 | + @bp.route('/TableVacuateInfo', methods=['POST']) | ||
| 127 | + @swag_from(table_vacuate_info.Api.api_doc) | ||
| 128 | + def api_table_vacuate_info(): | ||
| 129 | + """ | ||
| 130 | + 数据抽稀情况 | ||
| 131 | + """ | ||
| 132 | + return table_vacuate_info.Api().result | ||
| 133 | + | ||
| 134 | + @staticmethod | ||
| 135 | + @bp.route('/TableVacuateRef', methods=['POST']) | ||
| 136 | + @swag_from(table_vacuate_ref.Api.api_doc) | ||
| 137 | + def api_table_vacuate_ref(): | ||
| 138 | + """ | ||
| 139 | + 数据抽稀参考 | ||
| 140 | + """ | ||
| 141 | + return table_vacuate_ref.Api().result | ||
| 142 | + | ||
| 143 | + @staticmethod | ||
| 144 | + @bp.route('/TableVacuateDelete', methods=['POST']) | ||
| 145 | + @swag_from(table_vacuate_delete.Api.api_doc) | ||
| 146 | + def api_table_vacuate_delete(): | ||
| 147 | + """ | ||
| 148 | + 数据抽稀删除 | ||
| 149 | + """ | ||
| 150 | + return table_vacuate_delete.Api().result |
| @@ -40,6 +40,10 @@ class Api(ApiTemplate): | @@ -40,6 +40,10 @@ class Api(ApiTemplate): | ||
| 40 | tables = Table.query.order_by(Table.update_time.desc(),Table.name) | 40 | tables = Table.query.order_by(Table.update_time.desc(),Table.name) |
| 41 | else: | 41 | else: |
| 42 | tables = Table.query.order_by(Table.name) | 42 | tables = Table.query.order_by(Table.name) |
| 43 | + | ||
| 44 | + #过滤spatial_ref_sys | ||
| 45 | + tables = tables.filter(Table.name.notin_(["spatial_ref_sys"])) | ||
| 46 | + | ||
| 43 | if database_guid: | 47 | if database_guid: |
| 44 | tables = tables.filter_by(database_guid=database_guid) | 48 | tables = tables.filter_by(database_guid=database_guid) |
| 45 | if catalog_guid: | 49 | if catalog_guid: |
| @@ -13,7 +13,7 @@ import datetime | @@ -13,7 +13,7 @@ import datetime | ||
| 13 | import uuid | 13 | import uuid |
| 14 | 14 | ||
| 15 | from sqlalchemy.orm import Session | 15 | from sqlalchemy.orm import Session |
| 16 | - | 16 | +from app.util.component.SQLUtil import SQLUtil |
| 17 | from app.util.component.PGUtil import PGUtil | 17 | from app.util.component.PGUtil import PGUtil |
| 18 | from app.util.component.ModelVisitor import ModelVisitor | 18 | from app.util.component.ModelVisitor import ModelVisitor |
| 19 | from app.util.component.StructuredPrint import StructurePrint | 19 | from app.util.component.StructuredPrint import StructurePrint |
| @@ -70,6 +70,8 @@ class Api(ApiTemplate): | @@ -70,6 +70,8 @@ class Api(ApiTemplate): | ||
| 70 | data_session=None | 70 | data_session=None |
| 71 | result = {} | 71 | result = {} |
| 72 | sys_session = None | 72 | sys_session = None |
| 73 | + db_tuple = PGUtil.get_info_from_sqlachemy_uri(DES.decode(database.sqlalchemy_uri)) | ||
| 74 | + | ||
| 73 | try: | 75 | try: |
| 74 | sys_session = PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI) | 76 | sys_session = PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI) |
| 75 | 77 | ||
| @@ -89,16 +91,16 @@ class Api(ApiTemplate): | @@ -89,16 +91,16 @@ class Api(ApiTemplate): | ||
| 89 | 91 | ||
| 90 | # 更新空间表 | 92 | # 更新空间表 |
| 91 | # 增加表 | 93 | # 增加表 |
| 92 | - db_tables_names = self.add_spatail_table(database, pg_ds, sys_session,spatial_tables_names, this_time)# 实体库中空间表名 | 94 | + db_tables_names = self.add_spatail_table(database, pg_ds, sys_session,spatial_tables_names, this_time,db_tuple)# 实体库中空间表名 |
| 93 | 95 | ||
| 94 | # 删除/修改表 | 96 | # 删除/修改表 |
| 95 | - self.edit_spatial_table(pg_ds, sys_session,spatial_tables, db_tables_names, this_time) | 97 | + self.edit_spatial_table(pg_ds, sys_session,spatial_tables, db_tables_names, this_time,db_tuple) |
| 96 | 98 | ||
| 97 | # 空间表处理完毕 | 99 | # 空间表处理完毕 |
| 98 | sys_session.commit() | 100 | sys_session.commit() |
| 99 | 101 | ||
| 100 | # 处理抽稀表 | 102 | # 处理抽稀表 |
| 101 | - self.deal_vacuate_table(pg_ds,sys_session, database.guid) | 103 | + self.deal_vacuate_table(pg_ds,sys_session, database.guid,db_tuple) |
| 102 | 104 | ||
| 103 | # 空间表处理完毕 | 105 | # 空间表处理完毕 |
| 104 | sys_session.commit() | 106 | sys_session.commit() |
| @@ -133,11 +135,11 @@ class Api(ApiTemplate): | @@ -133,11 +135,11 @@ class Api(ApiTemplate): | ||
| 133 | # 增加新普通表 | 135 | # 增加新普通表 |
| 134 | 136 | ||
| 135 | self.add_common_table(data_session, sys_session, database_guid, real_common_tables_name, origin_common_tables_name, | 137 | self.add_common_table(data_session, sys_session, database_guid, real_common_tables_name, origin_common_tables_name, |
| 136 | - this_time) | 138 | + this_time,db_tuple) |
| 137 | 139 | ||
| 138 | # 删除、修改普通表 | 140 | # 删除、修改普通表 |
| 139 | self.edit_common_table(data_session,sys_session, database_guid, real_common_tables_name, origin_common_tables_name, | 141 | self.edit_common_table(data_session,sys_session, database_guid, real_common_tables_name, origin_common_tables_name, |
| 140 | - this_time) | 142 | + this_time,db_tuple) |
| 141 | 143 | ||
| 142 | sys_session.commit() | 144 | sys_session.commit() |
| 143 | result["data"] = "刷新数据成功!" | 145 | result["data"] = "刷新数据成功!" |
| @@ -168,7 +170,7 @@ class Api(ApiTemplate): | @@ -168,7 +170,7 @@ class Api(ApiTemplate): | ||
| 168 | sys_session.close() | 170 | sys_session.close() |
| 169 | return result | 171 | return result |
| 170 | 172 | ||
| 171 | - def add_spatail_table(self,database,pg_ds,sys_session,spatial_tables_names,this_time): | 173 | + def add_spatail_table(self,database,pg_ds,sys_session,spatial_tables_names,this_time,db_tuple): |
| 172 | ''' | 174 | ''' |
| 173 | 注册新增空间表 | 175 | 注册新增空间表 |
| 174 | :param database: | 176 | :param database: |
| @@ -196,10 +198,17 @@ class Api(ApiTemplate): | @@ -196,10 +198,17 @@ class Api(ApiTemplate): | ||
| 196 | if layer.GetName().__contains__("_vacuate_"): | 198 | if layer.GetName().__contains__("_vacuate_"): |
| 197 | continue | 199 | continue |
| 198 | 200 | ||
| 201 | + # 没有权限的表跳过 | ||
| 202 | + if not PGUtil.check_table_privilege(l_name, "SELECT", db_tuple[0], pg_ds): | ||
| 203 | + StructurePrint.print("用户{}对表{}没有select权限!".format(db_tuple[0], l_name), "warn") | ||
| 204 | + continue | ||
| 205 | + | ||
| 206 | + | ||
| 199 | # 范围统计和数量统计以100w为界限 | 207 | # 范围统计和数量统计以100w为界限 |
| 200 | query_count_layer: Layer = pg_ds.ExecuteSQL( | 208 | query_count_layer: Layer = pg_ds.ExecuteSQL( |
| 201 | '''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format( | 209 | '''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format( |
| 202 | l_name)) | 210 | l_name)) |
| 211 | + | ||
| 203 | feature_count = query_count_layer.GetFeature(0).GetField("ec") | 212 | feature_count = query_count_layer.GetFeature(0).GetField("ec") |
| 204 | # 要素少于100w可以精确统计 | 213 | # 要素少于100w可以精确统计 |
| 205 | if feature_count < 1000000: | 214 | if feature_count < 1000000: |
| @@ -218,12 +227,14 @@ class Api(ApiTemplate): | @@ -218,12 +227,14 @@ class Api(ApiTemplate): | ||
| 218 | 227 | ||
| 219 | StructurePrint.print("空间表增加!") | 228 | StructurePrint.print("空间表增加!") |
| 220 | 229 | ||
| 230 | + geom_type = GeometryAdapter.get_geometry_type(layer) | ||
| 231 | + | ||
| 221 | table_guid = uuid.uuid1().__str__() | 232 | table_guid = uuid.uuid1().__str__() |
| 222 | table = Table(guid=table_guid, | 233 | table = Table(guid=table_guid, |
| 223 | database_guid=database.guid, | 234 | database_guid=database.guid, |
| 224 | # alias=layer.GetName(), | 235 | # alias=layer.GetName(), |
| 225 | name=layer.GetName(), create_time=this_time, update_time=this_time, | 236 | name=layer.GetName(), create_time=this_time, update_time=this_time, |
| 226 | - table_type=GeometryAdapter.get_table_type(GeometryAdapter.get_geometry_type(layer)), | 237 | + table_type=GeometryAdapter.get_table_type(geom_type), |
| 227 | extent=extent, | 238 | extent=extent, |
| 228 | feature_count=feature_count | 239 | feature_count=feature_count |
| 229 | ) | 240 | ) |
| @@ -240,7 +251,7 @@ class Api(ApiTemplate): | @@ -240,7 +251,7 @@ class Api(ApiTemplate): | ||
| 240 | sys_session.add(column) | 251 | sys_session.add(column) |
| 241 | return db_tables_names | 252 | return db_tables_names |
| 242 | 253 | ||
| 243 | - def deal_vacuate_table(self,pg_ds,sys_session,database_guid): | 254 | + def deal_vacuate_table(self,pg_ds,sys_session,database_guid,db_tuple): |
| 244 | 255 | ||
| 245 | 256 | ||
| 246 | for i in range(pg_ds.GetLayerCount()): | 257 | for i in range(pg_ds.GetLayerCount()): |
| @@ -255,6 +266,10 @@ class Api(ApiTemplate): | @@ -255,6 +266,10 @@ class Api(ApiTemplate): | ||
| 255 | if layer.GetName().__contains__("_vacuate_"): | 266 | if layer.GetName().__contains__("_vacuate_"): |
| 256 | l_name = layer.GetName() | 267 | l_name = layer.GetName() |
| 257 | 268 | ||
| 269 | + # 没有权限的表跳过 | ||
| 270 | + if not PGUtil.check_table_privilege(l_name, "SELECT", db_tuple[0], pg_ds): | ||
| 271 | + StructurePrint.print("用户{}对表{}没有select权限!".format(db_tuple[0], l_name), "warn") | ||
| 272 | + continue | ||
| 258 | 273 | ||
| 259 | base_layer_name = l_name.split("_vacuate_")[0] | 274 | base_layer_name = l_name.split("_vacuate_")[0] |
| 260 | level = l_name.split("_")[-2] | 275 | level = l_name.split("_")[-2] |
| @@ -283,7 +298,9 @@ class Api(ApiTemplate): | @@ -283,7 +298,9 @@ class Api(ApiTemplate): | ||
| 283 | 298 | ||
| 284 | 299 | ||
| 285 | 300 | ||
| 286 | - def edit_spatial_table(self,pg_ds,sys_session,spatial_tables,db_tables_names,this_time): | 301 | + def edit_spatial_table(self,pg_ds,sys_session,spatial_tables,db_tables_names,this_time,db_tuple): |
| 302 | + | ||
| 303 | + | ||
| 287 | 304 | ||
| 288 | for table in spatial_tables: | 305 | for table in spatial_tables: |
| 289 | 306 | ||
| @@ -303,6 +320,12 @@ class Api(ApiTemplate): | @@ -303,6 +320,12 @@ class Api(ApiTemplate): | ||
| 303 | if layer.GetName().__contains__("_vacuate_"): | 320 | if layer.GetName().__contains__("_vacuate_"): |
| 304 | continue | 321 | continue |
| 305 | 322 | ||
| 323 | + # 没有权限的表跳过 | ||
| 324 | + if not PGUtil.check_table_privilege(l_name, "SELECT", db_tuple[0], pg_ds): | ||
| 325 | + StructurePrint.print("用户{}对表{}没有select权限!".format(db_tuple[0], l_name), "warn") | ||
| 326 | + sys_session.delete(table) | ||
| 327 | + continue | ||
| 328 | + | ||
| 306 | columns = table.relate_columns | 329 | columns = table.relate_columns |
| 307 | columns_names = [column.name for column in columns] | 330 | columns_names = [column.name for column in columns] |
| 308 | feature_defn: FeatureDefn = layer.GetLayerDefn() | 331 | feature_defn: FeatureDefn = layer.GetLayerDefn() |
| @@ -357,11 +380,18 @@ class Api(ApiTemplate): | @@ -357,11 +380,18 @@ class Api(ApiTemplate): | ||
| 357 | "extent": extent}) | 380 | "extent": extent}) |
| 358 | 381 | ||
| 359 | 382 | ||
| 360 | - def add_common_table(self,data_session,sys_session,database_guid,real_common_tables_name,origin_common_tables_name,this_time): | 383 | + def add_common_table(self,data_session,sys_session,database_guid,real_common_tables_name,origin_common_tables_name,this_time,db_tuple): |
| 361 | for table_name in real_common_tables_name: | 384 | for table_name in real_common_tables_name: |
| 362 | if table_name not in origin_common_tables_name: | 385 | if table_name not in origin_common_tables_name: |
| 363 | StructurePrint.print("{}非空间表增加!".format(table_name)) | 386 | StructurePrint.print("{}非空间表增加!".format(table_name)) |
| 364 | table_guid = uuid.uuid1().__str__() | 387 | table_guid = uuid.uuid1().__str__() |
| 388 | + | ||
| 389 | + | ||
| 390 | + # 没有权限的表跳过 | ||
| 391 | + if not SQLUtil.check_table_privilege(table_name, "SELECT", db_tuple[0], data_session): | ||
| 392 | + StructurePrint.print("用户{}对表{}没有select权限!".format(db_tuple[0], table_name), "warn") | ||
| 393 | + continue | ||
| 394 | + | ||
| 365 | count = data_session.execute('select count(*) from "{}"'.format(table_name)).fetchone()[0] | 395 | count = data_session.execute('select count(*) from "{}"'.format(table_name)).fetchone()[0] |
| 366 | 396 | ||
| 367 | table = Table(guid=table_guid, | 397 | table = Table(guid=table_guid, |
| @@ -402,7 +432,7 @@ class Api(ApiTemplate): | @@ -402,7 +432,7 @@ class Api(ApiTemplate): | ||
| 402 | for table in tables: | 432 | for table in tables: |
| 403 | sys_session.delete(table) | 433 | sys_session.delete(table) |
| 404 | 434 | ||
| 405 | - def edit_common_table(self,data_session,sys_session,database_guid,real_common_tables_name,origin_common_tables_name,this_time): | 435 | + def edit_common_table(self,data_session,sys_session,database_guid,real_common_tables_name,origin_common_tables_name,this_time,db_tuple): |
| 406 | for table_name in origin_common_tables_name: | 436 | for table_name in origin_common_tables_name: |
| 407 | tables = sys_session.query(Table).filter_by(name=table_name).filter_by(database_guid=database_guid).all() | 437 | tables = sys_session.query(Table).filter_by(name=table_name).filter_by(database_guid=database_guid).all() |
| 408 | for table in tables: | 438 | for table in tables: |
| @@ -411,6 +441,13 @@ class Api(ApiTemplate): | @@ -411,6 +441,13 @@ class Api(ApiTemplate): | ||
| 411 | sys_session.delete(table) | 441 | sys_session.delete(table) |
| 412 | # 修改表 | 442 | # 修改表 |
| 413 | else: | 443 | else: |
| 444 | + | ||
| 445 | + # 没有权限的表删除 | ||
| 446 | + if not SQLUtil.check_table_privilege(table_name, "SELECT", db_tuple[0], data_session): | ||
| 447 | + StructurePrint.print("用户{}对表{}没有select权限!".format(db_tuple[0], table_name), "warn") | ||
| 448 | + sys_session.delete(table) | ||
| 449 | + continue | ||
| 450 | + | ||
| 414 | columns = table.relate_columns | 451 | columns = table.relate_columns |
| 415 | columns_names = [column.name for column in columns] | 452 | columns_names = [column.name for column in columns] |
| 416 | 453 | ||
| @@ -448,15 +485,15 @@ class Api(ApiTemplate): | @@ -448,15 +485,15 @@ class Api(ApiTemplate): | ||
| 448 | sys_session.delete(column) | 485 | sys_session.delete(column) |
| 449 | 486 | ||
| 450 | # 修改要素量 | 487 | # 修改要素量 |
| 451 | - sql = 'select count(*) from "{}"'.format(table_name) | 488 | + # sql = 'select count(*) from "{}"'.format(table_name) |
| 489 | + # count = data_session.execute(sql).fetchone()[0] | ||
| 490 | + | ||
| 491 | + count = SQLUtil.get_table_count(table_name,data_session) | ||
| 452 | 492 | ||
| 453 | - count = data_session.execute(sql).fetchone()[0] | ||
| 454 | if not table.feature_count.__eq__(count): | 493 | if not table.feature_count.__eq__(count): |
| 455 | StructurePrint.print("{}表要素变化!".format(table_name)) | 494 | StructurePrint.print("{}表要素变化!".format(table_name)) |
| 456 | sys_session.query(Table).filter_by(guid=table.guid).update({"feature_count": count}) | 495 | sys_session.query(Table).filter_by(guid=table.guid).update({"feature_count": count}) |
| 457 | 496 | ||
| 458 | - | ||
| 459 | - | ||
| 460 | 497 | ||
| 461 | api_doc={ | 498 | api_doc={ |
| 462 | "tags":["管理接口"], | 499 | "tags":["管理接口"], |
| @@ -5,19 +5,23 @@ | @@ -5,19 +5,23 @@ | ||
| 5 | 5 | ||
| 6 | import datetime | 6 | import datetime |
| 7 | import traceback | 7 | import traceback |
| 8 | -from app.models import Table, Database, DES,Task,db | 8 | +from app.models import Table, Database, DES,Task,db,TableVacuate |
| 9 | 9 | ||
| 10 | from sqlalchemy.engine import ResultProxy | 10 | from sqlalchemy.engine import ResultProxy |
| 11 | from app.util.component.ApiTemplate import ApiTemplate | 11 | from app.util.component.ApiTemplate import ApiTemplate |
| 12 | from app.util.component.PGUtil import PGUtil | 12 | from app.util.component.PGUtil import PGUtil |
| 13 | from app.util.component.EntryDataVacuate import VacuateProcess,ThisTask,Process | 13 | from app.util.component.EntryDataVacuate import VacuateProcess,ThisTask,Process |
| 14 | +from app.util.component.StructuredPrint import StructurePrint | ||
| 15 | +from app.util.component.PGUtil import PGUtil | ||
| 14 | import multiprocessing | 16 | import multiprocessing |
| 15 | import uuid | 17 | import uuid |
| 16 | import configure | 18 | import configure |
| 17 | -from osgeo.ogr import DataSource | 19 | +from osgeo.ogr import DataSource,Layer |
| 18 | 20 | ||
| 19 | -class Api(ApiTemplate): | 21 | +from .table_vacuate_ref import Api as RefApi |
| 20 | 22 | ||
| 23 | +class Api(ApiTemplate): | ||
| 24 | + api_name = "数据抽稀" | ||
| 21 | def process(self): | 25 | def process(self): |
| 22 | 26 | ||
| 23 | res = {} | 27 | res = {} |
| @@ -26,15 +30,21 @@ class Api(ApiTemplate): | @@ -26,15 +30,21 @@ class Api(ApiTemplate): | ||
| 26 | try: | 30 | try: |
| 27 | table_guid = self.para.get("guid") | 31 | table_guid = self.para.get("guid") |
| 28 | table: Table = Table.query.filter_by(guid=table_guid).one_or_none() | 32 | table: Table = Table.query.filter_by(guid=table_guid).one_or_none() |
| 33 | + | ||
| 29 | if not table: | 34 | if not table: |
| 30 | raise Exception("数据不存在!") | 35 | raise Exception("数据不存在!") |
| 31 | 36 | ||
| 32 | - # 判断图层是否存在 | ||
| 33 | - | ||
| 34 | pg_ds :DataSource= PGUtil.open_pg_data_source(0,DES.decode(table.relate_database.sqlalchemy_uri)) | 37 | pg_ds :DataSource= PGUtil.open_pg_data_source(0,DES.decode(table.relate_database.sqlalchemy_uri)) |
| 35 | layer = pg_ds.GetLayerByName(table.name) | 38 | layer = pg_ds.GetLayerByName(table.name) |
| 39 | + # 判断图层是否存在 | ||
| 36 | if not layer: | 40 | if not layer: |
| 37 | raise Exception("图层不存在!") | 41 | raise Exception("图层不存在!") |
| 42 | + | ||
| 43 | + # 判断用户权限 | ||
| 44 | + db_tuple = PGUtil.get_info_from_sqlachemy_uri(DES.decode(table.relate_database.sqlalchemy_uri)) | ||
| 45 | + if not PGUtil.check_table_privilege(table.name,"SELECT",db_tuple[0],pg_ds): | ||
| 46 | + raise Exception("用户{}对表{}没有select权限!".format(db_tuple[0],table.name)) | ||
| 47 | + | ||
| 38 | if pg_ds: | 48 | if pg_ds: |
| 39 | pg_ds.Destroy() | 49 | pg_ds.Destroy() |
| 40 | 50 | ||
| @@ -46,17 +56,22 @@ class Api(ApiTemplate): | @@ -46,17 +56,22 @@ class Api(ApiTemplate): | ||
| 46 | res["result"] = False | 56 | res["result"] = False |
| 47 | res["msg"] = "非空间表!" | 57 | res["msg"] = "非空间表!" |
| 48 | return res | 58 | return res |
| 59 | + | ||
| 49 | # if table.is_vacuate==1: | 60 | # if table.is_vacuate==1: |
| 50 | # res["state"] = -1 | 61 | # res["state"] = -1 |
| 51 | # res["message"] = "已精化!" | 62 | # res["message"] = "已精化!" |
| 52 | # return res | 63 | # return res |
| 53 | 64 | ||
| 54 | 65 | ||
| 66 | + | ||
| 55 | # 初始化task | 67 | # 初始化task |
| 56 | task_guid = uuid.uuid1().__str__() | 68 | task_guid = uuid.uuid1().__str__() |
| 57 | vacuate_process = multiprocessing.Process(target=self.task,args=(table,task_guid)) | 69 | vacuate_process = multiprocessing.Process(target=self.task,args=(table,task_guid)) |
| 58 | vacuate_process.start() | 70 | vacuate_process.start() |
| 59 | 71 | ||
| 72 | + ref_api = RefApi() | ||
| 73 | + ref_api.para["guid"] = table_guid | ||
| 74 | + ref_grids = ref_api.process()["data"] | ||
| 60 | 75 | ||
| 61 | task = Task(guid=task_guid, | 76 | task = Task(guid=task_guid, |
| 62 | name="{}精化".format(table.name), | 77 | name="{}精化".format(table.name), |
| @@ -67,12 +82,15 @@ class Api(ApiTemplate): | @@ -67,12 +82,15 @@ class Api(ApiTemplate): | ||
| 67 | creator=self.para.get("creator"), | 82 | creator=self.para.get("creator"), |
| 68 | file_name=None, | 83 | file_name=None, |
| 69 | database_guid=table.database_guid, | 84 | database_guid=table.database_guid, |
| 70 | - process="精化中") | 85 | + process="精化中", |
| 86 | + parameter=",".join([str(x) for x in ref_grids])) | ||
| 87 | + | ||
| 71 | db.session.add(task) | 88 | db.session.add(task) |
| 72 | db.session.commit() | 89 | db.session.commit() |
| 73 | res["msg"] = "图层抽稀已提交!" | 90 | res["msg"] = "图层抽稀已提交!" |
| 74 | - res["data"] = table_guid | 91 | + res["data"] = task_guid |
| 75 | res["result"] = True | 92 | res["result"] = True |
| 93 | + | ||
| 76 | except Exception as e: | 94 | except Exception as e: |
| 77 | raise e | 95 | raise e |
| 78 | finally: | 96 | finally: |
| @@ -87,23 +105,34 @@ class Api(ApiTemplate): | @@ -87,23 +105,34 @@ class Api(ApiTemplate): | ||
| 87 | pg_ds = None | 105 | pg_ds = None |
| 88 | vacuate_process = None | 106 | vacuate_process = None |
| 89 | try: | 107 | try: |
| 90 | - | ||
| 91 | - sys_session= PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI) | ||
| 92 | - | 108 | + sys_session = PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI) |
| 93 | sys_session.query(Table).filter_by(guid=table.guid).update( | 109 | sys_session.query(Table).filter_by(guid=table.guid).update( |
| 94 | {"is_vacuate": 2, "update_time": datetime.datetime.now()}) | 110 | {"is_vacuate": 2, "update_time": datetime.datetime.now()}) |
| 95 | sys_session.commit() | 111 | sys_session.commit() |
| 96 | 112 | ||
| 113 | + | ||
| 97 | database = sys_session.query(Database).filter_by(guid=table.database_guid).one_or_none() | 114 | database = sys_session.query(Database).filter_by(guid=table.database_guid).one_or_none() |
| 98 | pg_session = PGUtil.get_db_session(DES.decode(database.sqlalchemy_uri)) | 115 | pg_session = PGUtil.get_db_session(DES.decode(database.sqlalchemy_uri)) |
| 99 | 116 | ||
| 100 | pg_ds :DataSource= PGUtil.open_pg_data_source(0,DES.decode(database.sqlalchemy_uri)) | 117 | pg_ds :DataSource= PGUtil.open_pg_data_source(0,DES.decode(database.sqlalchemy_uri)) |
| 101 | 118 | ||
| 119 | + | ||
| 120 | + #删除原有数据 | ||
| 121 | + tvs = sys_session.query(TableVacuate).filter_by(table_guid=table.guid).all() | ||
| 122 | + for tv in tvs : | ||
| 123 | + sys_session.delete(tv) | ||
| 124 | + # try: | ||
| 125 | + # pg_ds.DeleteLayer(tv.name) | ||
| 126 | + # except Exception as e : | ||
| 127 | + # StructurePrint.print("抽稀图层不存在!","warn") | ||
| 128 | + | ||
| 102 | # 创建抽稀过程 | 129 | # 创建抽稀过程 |
| 103 | options = ["OVERWRITE=yes", "GEOMETRY_NAME={}".format(PGUtil.get_geo_column(table.name,pg_session)), | 130 | options = ["OVERWRITE=yes", "GEOMETRY_NAME={}".format(PGUtil.get_geo_column(table.name,pg_session)), |
| 104 | "PRECISION=NO"] | 131 | "PRECISION=NO"] |
| 132 | + | ||
| 105 | layer = pg_ds.GetLayerByName(table.name) | 133 | layer = pg_ds.GetLayerByName(table.name) |
| 106 | - vacuate_process = VacuateProcess(layer, table.name, options,database.sqlalchemy_uri) | 134 | + |
| 135 | + vacuate_process:VacuateProcess = VacuateProcess(layer, table.name, options,database.sqlalchemy_uri) | ||
| 107 | 136 | ||
| 108 | 137 | ||
| 109 | for feature in layer: | 138 | for feature in layer: |
| @@ -112,14 +141,28 @@ class Api(ApiTemplate): | @@ -112,14 +141,28 @@ class Api(ApiTemplate): | ||
| 112 | if geo is not None: | 141 | if geo is not None: |
| 113 | vacuate_process.vacuate(geo) | 142 | vacuate_process.vacuate(geo) |
| 114 | 143 | ||
| 115 | - sys_session.query(Task).filter_by(guid=task_guid).update({"state":1,"update_time":datetime.datetime.now()}) | 144 | + |
| 145 | + #新增 | ||
| 146 | + for l in range(vacuate_process.max_level): | ||
| 147 | + lev = vacuate_process.t_grid_size.index(vacuate_process.this_gridsize[l]) | ||
| 148 | + | ||
| 149 | + table_vacuate = TableVacuate(guid=uuid.uuid1().__str__(), | ||
| 150 | + table_guid=table.guid, | ||
| 151 | + level=lev, | ||
| 152 | + name=vacuate_process.vacuate_layers[l].GetName(), | ||
| 153 | + pixel_distance=vacuate_process.this_gridsize[l]) | ||
| 154 | + sys_session.add(table_vacuate) | ||
| 155 | + | ||
| 156 | + sys_session.query(Task).filter_by(guid=task_guid).update({"state":1,"update_time":datetime.datetime.now(), | ||
| 157 | + "process": "精化完成"}) | ||
| 116 | sys_session.query(Table).filter_by(guid=table.guid).update( | 158 | sys_session.query(Table).filter_by(guid=table.guid).update( |
| 117 | {"is_vacuate": 1, "update_time": datetime.datetime.now()}) | 159 | {"is_vacuate": 1, "update_time": datetime.datetime.now()}) |
| 118 | sys_session.commit() | 160 | sys_session.commit() |
| 119 | 161 | ||
| 120 | except Exception as e: | 162 | except Exception as e: |
| 121 | try: | 163 | try: |
| 122 | - sys_session.query(Task).filter_by(guid=task_guid).update({"state": -1,"update_time":datetime.datetime.now()}) | 164 | + sys_session.query(Task).filter_by(guid=task_guid).update({"state": -1,"update_time":datetime.datetime.now(), |
| 165 | + "process": "精化失败"}) | ||
| 123 | sys_session.query(Table).filter_by(guid=table.guid).update( | 166 | sys_session.query(Table).filter_by(guid=table.guid).update( |
| 124 | {"is_vacuate": 0, "update_time": datetime.datetime.now()}) | 167 | {"is_vacuate": 0, "update_time": datetime.datetime.now()}) |
| 125 | 168 | ||
| @@ -129,7 +172,8 @@ class Api(ApiTemplate): | @@ -129,7 +172,8 @@ class Api(ApiTemplate): | ||
| 129 | task_guid=task_guid) | 172 | task_guid=task_guid) |
| 130 | sys_session.add(task_process) | 173 | sys_session.add(task_process) |
| 131 | sys_session.commit() | 174 | sys_session.commit() |
| 132 | - vacuate_process.rollback() | 175 | + if vacuate_process: |
| 176 | + vacuate_process.rollback() | ||
| 133 | 177 | ||
| 134 | print(traceback.format_exc()) | 178 | print(traceback.format_exc()) |
| 135 | except Exception as ee: | 179 | except Exception as ee: |
app/modules/manager/table_vacuate_delete.py
0 → 100644
| 1 | +# author: 4N | ||
| 2 | +# createtime: 2021/1/27 | ||
| 3 | +# email: nheweijun@sina.com | ||
| 4 | + | ||
| 5 | + | ||
| 6 | +import datetime | ||
| 7 | +import traceback | ||
| 8 | +from app.models import Table, Database, DES,Task,db,TableVacuate | ||
| 9 | + | ||
| 10 | +from sqlalchemy.engine import ResultProxy | ||
| 11 | +from app.util.component.ApiTemplate import ApiTemplate | ||
| 12 | +from app.util.component.PGUtil import PGUtil | ||
| 13 | +from app.util.component.EntryDataVacuate import Process | ||
| 14 | +from app.util.component.GeometryAdapter import GeometryAdapter | ||
| 15 | +from app.util.component.StructuredPrint import StructurePrint | ||
| 16 | +import multiprocessing | ||
| 17 | +import uuid | ||
| 18 | +import configure | ||
| 19 | +from osgeo.ogr import DataSource,Layer,Geometry | ||
| 20 | +from osgeo import ogr | ||
| 21 | + | ||
| 22 | +class Api(ApiTemplate): | ||
| 23 | + api_name = "删除抽稀表" | ||
| 24 | + def process(self): | ||
| 25 | + | ||
| 26 | + res = {} | ||
| 27 | + res["data"] = {} | ||
| 28 | + pg_ds = None | ||
| 29 | + try: | ||
| 30 | + table_guid = self.para.get("guid") | ||
| 31 | + table: Table = Table.query.filter_by(guid=table_guid).one_or_none() | ||
| 32 | + grid = None | ||
| 33 | + if not self.para.get("grid"): | ||
| 34 | + raise Exception("请输入grids参数!") | ||
| 35 | + else: | ||
| 36 | + grid = float(self.para.get("grid")) | ||
| 37 | + | ||
| 38 | + if not table: | ||
| 39 | + raise Exception("数据不存在!") | ||
| 40 | + | ||
| 41 | + # 判断图层是否存在 | ||
| 42 | + pg_ds :DataSource= PGUtil.open_pg_data_source(0,DES.decode(table.relate_database.sqlalchemy_uri)) | ||
| 43 | + layer = pg_ds.GetLayerByName(table.name) | ||
| 44 | + | ||
| 45 | + # 判断用户权限 | ||
| 46 | + # user, pw, host, port, database = PGUtil.get_info_from_sqlachemy_uri(DES.decode(table.relate_database.sqlalchemy_uri)) | ||
| 47 | + # query_role:Layer = pg_ds.ExecuteSQL("SELECT rolcreatedb FROM pg_roles WHERE rolname='{}'".format(user)) | ||
| 48 | + # if not query_role.GetFeature(0).GetField("rolcreatedb"): | ||
| 49 | + # raise Exception("用户不具备建表权限!") | ||
| 50 | + | ||
| 51 | + if not layer: | ||
| 52 | + raise Exception("图层不存在!") | ||
| 53 | + | ||
| 54 | + #删除数据 | ||
| 55 | + tvs = db.session.query(TableVacuate).filter_by(pixel_distance=grid, table_guid=table.guid).all() | ||
| 56 | + if not tvs: | ||
| 57 | + raise Exception("数据不存在!") | ||
| 58 | + for tv in tvs : | ||
| 59 | + db.session.delete(tv) | ||
| 60 | + try: | ||
| 61 | + pg_ds.DeleteLayer(tv.name) | ||
| 62 | + except Exception as e : | ||
| 63 | + StructurePrint.print("抽稀图层不存在!","warn") | ||
| 64 | + db.session.commit() | ||
| 65 | + res["result"] = True | ||
| 66 | + | ||
| 67 | + except Exception as e: | ||
| 68 | + raise e | ||
| 69 | + finally: | ||
| 70 | + if pg_ds: | ||
| 71 | + pg_ds.Destroy() | ||
| 72 | + return res | ||
| 73 | + | ||
| 74 | + | ||
| 75 | + api_doc = { | ||
| 76 | + "tags": ["管理接口"], | ||
| 77 | + "parameters": [ | ||
| 78 | + {"name": "guid", | ||
| 79 | + "in": "formData", | ||
| 80 | + "type": "string", | ||
| 81 | + "description": "表guid", "required": "true"}, | ||
| 82 | + {"name": "grid", | ||
| 83 | + "in": "formData", | ||
| 84 | + "type": "string", | ||
| 85 | + "description": "网格大小", "required": "true"} | ||
| 86 | + ], | ||
| 87 | + "responses": { | ||
| 88 | + 200: { | ||
| 89 | + "schema": { | ||
| 90 | + "properties": { | ||
| 91 | + } | ||
| 92 | + } | ||
| 93 | + } | ||
| 94 | + } | ||
| 95 | + } |
app/modules/manager/table_vacuate_info.py
0 → 100644
| 1 | +# author: 4N | ||
| 2 | +# createtime: 2021/1/27 | ||
| 3 | +# email: nheweijun@sina.com | ||
| 4 | + | ||
| 5 | + | ||
| 6 | +from app.models import Table,TableVacuate,Task | ||
| 7 | +from app.util.component.ApiTemplate import ApiTemplate | ||
| 8 | +from app.util.component.VacuateConf import VacuateConf | ||
| 9 | +import collections | ||
| 10 | +import json | ||
| 11 | + | ||
| 12 | +import copy | ||
| 13 | +class Api(ApiTemplate): | ||
| 14 | + api_name = "抽稀info" | ||
| 15 | + def process(self): | ||
| 16 | + | ||
| 17 | + res = {} | ||
| 18 | + try: | ||
| 19 | + | ||
| 20 | + lonlat_gridsize = VacuateConf.lonlat_gridsize | ||
| 21 | + project_gridsize = VacuateConf.project_gridsize | ||
| 22 | + table_guid = self.para.get("guid") | ||
| 23 | + | ||
| 24 | + table: Table = Table.query.filter_by(guid=table_guid).one_or_none() | ||
| 25 | + if not table: | ||
| 26 | + raise Exception("数据不存在!") | ||
| 27 | + tvs = TableVacuate.query.filter_by(table_guid=table_guid).all() | ||
| 28 | + dat = collections.OrderedDict() | ||
| 29 | + if float(table.extent.split(",")[0])<180: | ||
| 30 | + grid_size = copy.copy(lonlat_gridsize) | ||
| 31 | + else: | ||
| 32 | + grid_size = copy.copy(project_gridsize) | ||
| 33 | + | ||
| 34 | + now_grid = [tv.pixel_distance for tv in tvs] | ||
| 35 | + | ||
| 36 | + grid_size.reverse() | ||
| 37 | + | ||
| 38 | + # 正在精华的任务 | ||
| 39 | + task_running = Task.query.filter_by(task_type=2,table_guid=table_guid,state=0).all() | ||
| 40 | + grid_running = [] | ||
| 41 | + | ||
| 42 | + for t in task_running: | ||
| 43 | + grid_running.extend(t.parameter.split(",")) | ||
| 44 | + | ||
| 45 | + for grid in grid_size: | ||
| 46 | + if grid in now_grid: | ||
| 47 | + dat[str(grid)] = 1 | ||
| 48 | + else: | ||
| 49 | + dat[str(grid)] = 0 | ||
| 50 | + if str(grid) in grid_running: | ||
| 51 | + dat[str(grid)] = 2 | ||
| 52 | + | ||
| 53 | + res["data"] = json.dumps(dat) | ||
| 54 | + res["result"] = True | ||
| 55 | + | ||
| 56 | + except Exception as e: | ||
| 57 | + raise e | ||
| 58 | + return res | ||
| 59 | + | ||
| 60 | + api_doc = { | ||
| 61 | + "tags": ["管理接口"], | ||
| 62 | + "parameters": [ | ||
| 63 | + {"name": "guid", | ||
| 64 | + "in": "formData", | ||
| 65 | + "type": "string", | ||
| 66 | + "description": "表guid", "required": "true"}, | ||
| 67 | + ], | ||
| 68 | + "responses": { | ||
| 69 | + 200: { | ||
| 70 | + "schema": { | ||
| 71 | + "properties": { | ||
| 72 | + } | ||
| 73 | + } | ||
| 74 | + } | ||
| 75 | + } | ||
| 76 | + } |
app/modules/manager/table_vacuate_one.py
0 → 100644
| 1 | +# author: 4N | ||
| 2 | +# createtime: 2021/1/27 | ||
| 3 | +# email: nheweijun@sina.com | ||
| 4 | + | ||
| 5 | + | ||
| 6 | +import datetime | ||
| 7 | +import traceback | ||
| 8 | +from app.models import Table, Database, DES,Task,db,TableVacuate | ||
| 9 | +from app.util.component.ApiTemplate import ApiTemplate | ||
| 10 | +from app.util.component.PGUtil import PGUtil | ||
| 11 | +from app.util.component.EntryDataVacuate import Process | ||
| 12 | +import multiprocessing | ||
| 13 | +import uuid | ||
| 14 | +import configure | ||
| 15 | +from osgeo.ogr import DataSource,Layer,Geometry | ||
| 16 | +from osgeo import ogr | ||
| 17 | +from app.util.component.StructuredPrint import StructurePrint | ||
| 18 | +from app.util.component.VacuateConf import VacuateConf | ||
| 19 | + | ||
| 20 | +class Api(ApiTemplate): | ||
| 21 | + api_name = "单独抽稀" | ||
| 22 | + def process(self): | ||
| 23 | + | ||
| 24 | + res = {} | ||
| 25 | + res["data"] = {} | ||
| 26 | + db_session = None | ||
| 27 | + try: | ||
| 28 | + table_guid = self.para.get("guid") | ||
| 29 | + grids = [] | ||
| 30 | + if not self.para.get("grids"): | ||
| 31 | + raise Exception("请输入grids参数!") | ||
| 32 | + else: | ||
| 33 | + grids = [float(x) for x in self.para.get("grids").split(",")] | ||
| 34 | + grids.sort() | ||
| 35 | + | ||
| 36 | + table: Table = Table.query.filter_by(guid=table_guid).one_or_none() | ||
| 37 | + | ||
| 38 | + if not table: | ||
| 39 | + raise Exception("数据不存在!") | ||
| 40 | + | ||
| 41 | + # 判断图层是否存在 | ||
| 42 | + | ||
| 43 | + pg_ds :DataSource= PGUtil.open_pg_data_source(0,DES.decode(table.relate_database.sqlalchemy_uri)) | ||
| 44 | + layer = pg_ds.GetLayerByName(table.name) | ||
| 45 | + | ||
| 46 | + # 判断用户权限 | ||
| 47 | + db_tuple = PGUtil.get_info_from_sqlachemy_uri(DES.decode(table.relate_database.sqlalchemy_uri)) | ||
| 48 | + if not PGUtil.check_table_privilege(table.name,"SELECT",db_tuple[0],pg_ds): | ||
| 49 | + raise Exception("用户{}对表{}没有select权限!".format(db_tuple[0],table.name)) | ||
| 50 | + | ||
| 51 | + if not layer: | ||
| 52 | + raise Exception("图层不存在!") | ||
| 53 | + if pg_ds: | ||
| 54 | + pg_ds.Destroy() | ||
| 55 | + | ||
| 56 | + | ||
| 57 | + | ||
| 58 | + if Task.query.filter_by(table_guid=table_guid,state=0).one_or_none(): | ||
| 59 | + res["result"] = False | ||
| 60 | + res["msg"] = "数据精化中!" | ||
| 61 | + return res | ||
| 62 | + if table.table_type==0: | ||
| 63 | + res["result"] = False | ||
| 64 | + res["msg"] = "非空间表!" | ||
| 65 | + return res | ||
| 66 | + | ||
| 67 | + # if table.is_vacuate==1: | ||
| 68 | + # res["state"] = -1 | ||
| 69 | + # res["message"] = "已精化!" | ||
| 70 | + # return res | ||
| 71 | + | ||
| 72 | + # 初始化task | ||
| 73 | + task_guid = uuid.uuid1().__str__() | ||
| 74 | + | ||
| 75 | + vacuate_process = multiprocessing.Process(target=self.task,args=(table,task_guid,grids)) | ||
| 76 | + vacuate_process.start() | ||
| 77 | + | ||
| 78 | + | ||
| 79 | + task = Task(guid=task_guid, | ||
| 80 | + name="{}精化,网格大小:{}".format(table.name,self.para.get("grids")), | ||
| 81 | + table_guid=table_guid, | ||
| 82 | + create_time=datetime.datetime.now(), | ||
| 83 | + state=0, | ||
| 84 | + task_type=2, | ||
| 85 | + creator=self.para.get("creator"), | ||
| 86 | + file_name=None, | ||
| 87 | + database_guid=table.database_guid, | ||
| 88 | + process="精化中", | ||
| 89 | + parameter=self.para.get("grids")) | ||
| 90 | + | ||
| 91 | + db.session.add(task) | ||
| 92 | + db.session.commit() | ||
| 93 | + res["msg"] = "图层抽稀已提交!" | ||
| 94 | + res["data"] = task_guid | ||
| 95 | + res["result"] = True | ||
| 96 | + | ||
| 97 | + except Exception as e: | ||
| 98 | + raise e | ||
| 99 | + finally: | ||
| 100 | + if db_session: | ||
| 101 | + db_session.close() | ||
| 102 | + return res | ||
| 103 | + | ||
| 104 | + def task(self,table,task_guid,grids): | ||
| 105 | + | ||
| 106 | + sys_session = None | ||
| 107 | + pg_session = None | ||
| 108 | + pg_ds = None | ||
| 109 | + vacuate_process = None | ||
| 110 | + origin_vacuate = table.is_vacuate | ||
| 111 | + | ||
| 112 | + try: | ||
| 113 | + sys_session = PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI) | ||
| 114 | + sys_session.query(Table).filter_by(guid=table.guid).update( | ||
| 115 | + {"is_vacuate": 2, "update_time": datetime.datetime.now()}) | ||
| 116 | + sys_session.commit() | ||
| 117 | + | ||
| 118 | + | ||
| 119 | + database = sys_session.query(Database).filter_by(guid=table.database_guid).one_or_none() | ||
| 120 | + pg_session = PGUtil.get_db_session(DES.decode(database.sqlalchemy_uri)) | ||
| 121 | + | ||
| 122 | + pg_ds :DataSource= PGUtil.open_pg_data_source(1,DES.decode(database.sqlalchemy_uri)) | ||
| 123 | + | ||
| 124 | + # 创建抽稀过程 | ||
| 125 | + options = ["OVERWRITE=yes", "GEOMETRY_NAME={}".format(PGUtil.get_geo_column(table.name,pg_session)), | ||
| 126 | + "PRECISION=NO"] | ||
| 127 | + | ||
| 128 | + layer = pg_ds.GetLayerByName(table.name) | ||
| 129 | + | ||
| 130 | + vacuate_process:VacuateProcess = VacuateProcess(layer, table.name, options,database.sqlalchemy_uri,grids) | ||
| 131 | + | ||
| 132 | + | ||
| 133 | + for feature in layer: | ||
| 134 | + geo = feature.GetGeometryRef() | ||
| 135 | + #插入抽稀图层 | ||
| 136 | + if geo is not None: | ||
| 137 | + vacuate_process.vacuate(geo) | ||
| 138 | + | ||
| 139 | + #删除原有数据 | ||
| 140 | + for grid in grids: | ||
| 141 | + tvs = sys_session.query(TableVacuate).filter_by(pixel_distance=grid,table_guid=table.guid).all() | ||
| 142 | + for tv in tvs : | ||
| 143 | + sys_session.delete(tv) | ||
| 144 | + | ||
| 145 | + | ||
| 146 | + #新增 | ||
| 147 | + for l in range(vacuate_process.max_level): | ||
| 148 | + layer_name = vacuate_process.vacuate_layers[l].GetName() | ||
| 149 | + lev = layer_name.split("_")[-2] | ||
| 150 | + | ||
| 151 | + table_vacuate = TableVacuate(guid=uuid.uuid1().__str__(), | ||
| 152 | + table_guid=table.guid, | ||
| 153 | + level=int(lev), | ||
| 154 | + name=layer_name, | ||
| 155 | + pixel_distance=vacuate_process.this_gridsize[l]) | ||
| 156 | + sys_session.add(table_vacuate) | ||
| 157 | + | ||
| 158 | + sys_session.query(Task).filter_by(guid=task_guid).update({"state":1,"update_time":datetime.datetime.now(), | ||
| 159 | + "process" : "精化完成"}) | ||
| 160 | + sys_session.query(Table).filter_by(guid=table.guid).update( | ||
| 161 | + {"is_vacuate": 1, "update_time": datetime.datetime.now()}) | ||
| 162 | + sys_session.commit() | ||
| 163 | + | ||
| 164 | + except Exception as e: | ||
| 165 | + try: | ||
| 166 | + sys_session.query(Task).filter_by(guid=task_guid).update({"state": -1,"update_time":datetime.datetime.now(), | ||
| 167 | + "process": "精化失败"}) | ||
| 168 | + sys_session.query(Table).filter_by(guid=table.guid).update( | ||
| 169 | + {"is_vacuate": origin_vacuate, "update_time": datetime.datetime.now()}) | ||
| 170 | + | ||
| 171 | + message = "{} {}".format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), e.__str__()) | ||
| 172 | + task_process_guid = uuid.uuid1().__str__() | ||
| 173 | + task_process = Process(guid=task_process_guid, message=message, time=datetime.datetime.now(), | ||
| 174 | + task_guid=task_guid) | ||
| 175 | + sys_session.add(task_process) | ||
| 176 | + sys_session.commit() | ||
| 177 | + if vacuate_process: | ||
| 178 | + vacuate_process.rollback() | ||
| 179 | + | ||
| 180 | + print(traceback.format_exc()) | ||
| 181 | + except Exception as ee: | ||
| 182 | + print(traceback.format_exc()) | ||
| 183 | + finally: | ||
| 184 | + try: | ||
| 185 | + if vacuate_process: | ||
| 186 | + vacuate_process.end() | ||
| 187 | + if sys_session: | ||
| 188 | + sys_session.close() | ||
| 189 | + if pg_session: | ||
| 190 | + pg_session.close() | ||
| 191 | + if pg_ds: | ||
| 192 | + pg_ds.Destroy() | ||
| 193 | + except: | ||
| 194 | + print(traceback.format_exc()) | ||
| 195 | + | ||
| 196 | + api_doc = { | ||
| 197 | + "tags": ["管理接口"], | ||
| 198 | + "parameters": [ | ||
| 199 | + {"name": "guid", | ||
| 200 | + "in": "formData", | ||
| 201 | + "type": "string", | ||
| 202 | + "description": "表guid", "required": "true"}, | ||
| 203 | + {"name": "grids", | ||
| 204 | + "in": "formData", | ||
| 205 | + "type": "string", | ||
| 206 | + "description": "需要抽稀的网格大小,以逗号相隔", "required": "true"} | ||
| 207 | + ], | ||
| 208 | + "responses": { | ||
| 209 | + 200: { | ||
| 210 | + "schema": { | ||
| 211 | + "properties": { | ||
| 212 | + } | ||
| 213 | + } | ||
| 214 | + } | ||
| 215 | + } | ||
| 216 | + } | ||
| 217 | + | ||
| 218 | + | ||
| 219 | +class VacuateProcess: | ||
| 220 | + ''' | ||
| 221 | + 抽稀类 | ||
| 222 | + ''' | ||
| 223 | + | ||
| 224 | + max_level=0 | ||
| 225 | + fill_dict={} | ||
| 226 | + vacuate_layers={} | ||
| 227 | + vacuate_layers_gridsize={} | ||
| 228 | + pg_ds_dict = {} | ||
| 229 | + #被抽吸图层的范围 | ||
| 230 | + extent=[] | ||
| 231 | + is_spatial=False | ||
| 232 | + #该抽稀过程的抽稀网格 | ||
| 233 | + this_gridsize=[] | ||
| 234 | + | ||
| 235 | + | ||
| 236 | + def __init__(self,layer:Layer,new_layer_name, options,sqlalchemy_uri,grids): | ||
| 237 | + | ||
| 238 | + #是空间图层才初始化 | ||
| 239 | + if layer.GetExtent()[0] > 0 or layer.GetExtent()[0] < 0: | ||
| 240 | + | ||
| 241 | + self.is_spatial=True | ||
| 242 | + | ||
| 243 | + # 判断需要抽稀多少级 | ||
| 244 | + | ||
| 245 | + extent = layer.GetExtent() | ||
| 246 | + self.extent=extent | ||
| 247 | + | ||
| 248 | + layer.SetSpatialFilter(None) | ||
| 249 | + layer.ResetReading() | ||
| 250 | + | ||
| 251 | + self.this_gridsize = grids | ||
| 252 | + self.max_level = len(grids) | ||
| 253 | + | ||
| 254 | + | ||
| 255 | + # 创建抽稀ds | ||
| 256 | + for l in range(self.max_level): | ||
| 257 | + pg_ds_l: DataSource = PGUtil.open_pg_data_source(1, DES.decode(sqlalchemy_uri)) | ||
| 258 | + pg_ds_l.StartTransaction() | ||
| 259 | + self.pg_ds_dict[l] = pg_ds_l | ||
| 260 | + | ||
| 261 | + # 生成抽稀图层 | ||
| 262 | + options = options[1:] | ||
| 263 | + options.append("OVERWRITE=yes") | ||
| 264 | + options.append("LAUNDER=no") | ||
| 265 | + for l in range(self.max_level): | ||
| 266 | + this_grid_len = self.this_gridsize[l] | ||
| 267 | + | ||
| 268 | + self.vacuate_layers_gridsize[l] = this_grid_len | ||
| 269 | + | ||
| 270 | + pg = self.pg_ds_dict[l] | ||
| 271 | + | ||
| 272 | + if this_grid_len<1: | ||
| 273 | + grid_name = str(this_grid_len).split(".")[-1] | ||
| 274 | + if this_grid_len.__eq__(0.000075): | ||
| 275 | + grid_name = "000075" | ||
| 276 | + else: | ||
| 277 | + grid_name = str(int(this_grid_len)) | ||
| 278 | + | ||
| 279 | + # 抽稀图层是点面混合的 | ||
| 280 | + # 抽稀表有固定的命名规则 | ||
| 281 | + # 抽稀表一定要覆盖 | ||
| 282 | + | ||
| 283 | + this_grid_szie = VacuateConf.project_gridsize if VacuateConf.project_gridsize.__contains__(this_grid_len) else VacuateConf.lonlat_gridsize | ||
| 284 | + | ||
| 285 | + lev = this_grid_szie.index(this_grid_len) | ||
| 286 | + print("{}:{}".format(grid_name, lev)) | ||
| 287 | + vl = pg.CreateLayer("{}_vacuate_{}_{}".format(new_layer_name, lev, grid_name), layer.GetSpatialRef(), | ||
| 288 | + ogr.wkbUnknown, options) | ||
| 289 | + # 抽稀表不需要属性 | ||
| 290 | + # vl.CreateFields(schema) | ||
| 291 | + self.vacuate_layers[l] = vl | ||
| 292 | + | ||
| 293 | + else: | ||
| 294 | + pass | ||
| 295 | + | ||
| 296 | + | ||
| 297 | + def vacuate(self,g): | ||
| 298 | + | ||
| 299 | + if self.is_spatial: | ||
| 300 | + | ||
| 301 | + # 插入到所有抽稀图层中 | ||
| 302 | + for level in range(self.max_level): | ||
| 303 | + | ||
| 304 | + center: Geometry = g.Centroid() | ||
| 305 | + | ||
| 306 | + extent = g.GetEnvelope() | ||
| 307 | + long_extent= extent[1]-extent[0] | ||
| 308 | + lat_extent = extent[3]-extent[2] | ||
| 309 | + | ||
| 310 | + this_grid_len =self.vacuate_layers_gridsize[level] | ||
| 311 | + | ||
| 312 | + row = int((center.GetY() - self.extent[2]) / this_grid_len) | ||
| 313 | + col = int((center.GetX() - self.extent[0]) / this_grid_len) | ||
| 314 | + key = "{}.{}.{}".format(level, row, col) | ||
| 315 | + | ||
| 316 | + if not self.fill_dict.get(key): | ||
| 317 | + self.fill_dict[key] = 0 | ||
| 318 | + if self.fill_dict[key] == 0: | ||
| 319 | + | ||
| 320 | + vacuate_layer: Layer = self.vacuate_layers.get(level) | ||
| 321 | + feat = ogr.Feature(vacuate_layer.GetLayerDefn()) | ||
| 322 | + # 如果图形比网格小,直接存储其中心点 | ||
| 323 | + if this_grid_len>long_extent and this_grid_len>lat_extent: | ||
| 324 | + feat.SetGeometry(center) | ||
| 325 | + else: | ||
| 326 | + feat.SetGeometry(g) | ||
| 327 | + vacuate_layer.CreateFeature(feat) | ||
| 328 | + self.fill_dict[key] += 1 | ||
| 329 | + | ||
| 330 | + def end(self): | ||
| 331 | + for pg in self.pg_ds_dict.values(): | ||
| 332 | + pg.Destroy() | ||
| 333 | + | ||
| 334 | + def rollback(self): | ||
| 335 | + for pg in self.pg_ds_dict.values(): | ||
| 336 | + pg.RollbackTransaction() |
app/modules/manager/table_vacuate_ref.py
0 → 100644
| 1 | +# author: 4N | ||
| 2 | +# createtime: 2021/1/27 | ||
| 3 | +# email: nheweijun@sina.com | ||
| 4 | + | ||
| 5 | + | ||
| 6 | +import datetime | ||
| 7 | +import traceback | ||
| 8 | +from app.models import Table, Database, DES,Task,db,TableVacuate | ||
| 9 | + | ||
| 10 | +from sqlalchemy.engine import ResultProxy | ||
| 11 | +from app.util.component.ApiTemplate import ApiTemplate | ||
| 12 | +from app.util.component.PGUtil import PGUtil | ||
| 13 | +from app.util.component.EntryDataVacuate import Process | ||
| 14 | +from app.util.component.GeometryAdapter import GeometryAdapter | ||
| 15 | +from app.util.component.StructuredPrint import StructurePrint | ||
| 16 | +import multiprocessing | ||
| 17 | +import uuid | ||
| 18 | +import configure | ||
| 19 | +from osgeo.ogr import DataSource,Layer,Geometry | ||
| 20 | +from osgeo import ogr | ||
| 21 | +from app.util.component.VacuateConf import VacuateConf | ||
| 22 | +import copy | ||
| 23 | +class Api(ApiTemplate): | ||
| 24 | + api_name = "推荐抽稀" | ||
| 25 | + def process(self): | ||
| 26 | + | ||
| 27 | + res = {} | ||
| 28 | + res["data"] = {} | ||
| 29 | + pg_ds = None | ||
| 30 | + try: | ||
| 31 | + table_guid = self.para.get("guid") | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + table: Table = Table.query.filter_by(guid=table_guid).one_or_none() | ||
| 35 | + | ||
| 36 | + | ||
| 37 | + if not table: | ||
| 38 | + raise Exception("数据不存在!") | ||
| 39 | + | ||
| 40 | + # 判断图层是否存在 | ||
| 41 | + | ||
| 42 | + pg_ds :DataSource= PGUtil.open_pg_data_source(0,DES.decode(table.relate_database.sqlalchemy_uri)) | ||
| 43 | + layer = pg_ds.GetLayerByName(table.name) | ||
| 44 | + | ||
| 45 | + # 判断用户权限 | ||
| 46 | + user, pw, host, port, database = PGUtil.get_info_from_sqlachemy_uri(DES.decode(table.relate_database.sqlalchemy_uri)) | ||
| 47 | + query_role:Layer = pg_ds.ExecuteSQL("SELECT rolcreatedb FROM pg_roles WHERE rolname='{}'".format(user)) | ||
| 48 | + if not query_role.GetFeature(0).GetField("rolcreatedb"): | ||
| 49 | + raise Exception("用户不具备建表权限!") | ||
| 50 | + | ||
| 51 | + if not layer: | ||
| 52 | + raise Exception("图层不存在!") | ||
| 53 | + | ||
| 54 | + | ||
| 55 | + lonlat_gridsize = copy.deepcopy(VacuateConf.lonlat_gridsize) | ||
| 56 | + project_gridsize = copy.deepcopy(VacuateConf.project_gridsize) | ||
| 57 | + least_vacuate_count = copy.deepcopy(VacuateConf.least_vacuate_count) | ||
| 58 | + | ||
| 59 | + this_gridsize = [] | ||
| 60 | + max_level = 0 | ||
| 61 | + # 是空间图层才初始化 | ||
| 62 | + if layer.GetExtent()[0] > 0 or layer.GetExtent()[0] < 0: | ||
| 63 | + | ||
| 64 | + | ||
| 65 | + # 判断需要抽稀多少级 | ||
| 66 | + lc = layer.GetFeatureCount() | ||
| 67 | + extent = layer.GetExtent() | ||
| 68 | + | ||
| 69 | + # 判断疏密程度 | ||
| 70 | + p_x = (extent[1] - extent[0]) / 10.0 | ||
| 71 | + p_y = (extent[3] - extent[2]) / 10.0 | ||
| 72 | + fill_precent = 0 | ||
| 73 | + StructurePrint.print("判断疏密") | ||
| 74 | + for ix in range(10): | ||
| 75 | + for iy in range(10): | ||
| 76 | + grid_extent = [extent[0] + ix * p_x, extent[0] + ix * p_x + p_x, extent[2] + iy * p_y, | ||
| 77 | + extent[2] + iy * p_y + p_y] | ||
| 78 | + poly = GeometryAdapter.envelop_2_polygon(grid_extent) | ||
| 79 | + | ||
| 80 | + layer.SetSpatialFilter(None) | ||
| 81 | + layer.SetSpatialFilter(poly) | ||
| 82 | + layer.ResetReading() | ||
| 83 | + if layer.GetNextFeature(): | ||
| 84 | + fill_precent += 1 | ||
| 85 | + | ||
| 86 | + print(fill_precent) | ||
| 87 | + StructurePrint.print("判断疏密结束") | ||
| 88 | + | ||
| 89 | + layer.SetSpatialFilter(None) | ||
| 90 | + layer.ResetReading() | ||
| 91 | + # 固有疏密程度 | ||
| 92 | + original_density = 8 | ||
| 93 | + | ||
| 94 | + if extent[0] > 180: | ||
| 95 | + t_grid_size = project_gridsize | ||
| 96 | + else: | ||
| 97 | + t_grid_size = lonlat_gridsize | ||
| 98 | + for grid_size in t_grid_size: | ||
| 99 | + # 最少抽稀个数 | ||
| 100 | + if lc > least_vacuate_count: | ||
| 101 | + # 网格数至少大于 | ||
| 102 | + if ((extent[1] - extent[0]) * (extent[3] - extent[2])) / ( | ||
| 103 | + grid_size ** 2) > least_vacuate_count: | ||
| 104 | + # 要素数量大于网格数量 | ||
| 105 | + # 要考虑图层的疏密程度,original_density*(100.0/fill_precent) 为疏密指数 | ||
| 106 | + if lc * original_density * (100.0 / fill_precent) > ( | ||
| 107 | + (extent[1] - extent[0]) * (extent[3] - extent[2])) / (grid_size ** 2): | ||
| 108 | + this_gridsize.append(grid_size) | ||
| 109 | + max_level += 1 | ||
| 110 | + | ||
| 111 | + res["data"] = this_gridsize | ||
| 112 | + res["result"] = True | ||
| 113 | + | ||
| 114 | + | ||
| 115 | + except Exception as e: | ||
| 116 | + raise e | ||
| 117 | + finally: | ||
| 118 | + if pg_ds: | ||
| 119 | + pg_ds.Destroy() | ||
| 120 | + return res | ||
| 121 | + | ||
| 122 | + | ||
| 123 | + api_doc = { | ||
| 124 | + "tags": ["管理接口"], | ||
| 125 | + "parameters": [ | ||
| 126 | + {"name": "guid", | ||
| 127 | + "in": "formData", | ||
| 128 | + "type": "string", | ||
| 129 | + "description": "表guid", "required": "true"} | ||
| 130 | + ], | ||
| 131 | + "responses": { | ||
| 132 | + 200: { | ||
| 133 | + "schema": { | ||
| 134 | + "properties": { | ||
| 135 | + } | ||
| 136 | + } | ||
| 137 | + } | ||
| 138 | + } | ||
| 139 | + } |
| @@ -16,6 +16,7 @@ from functools import lru_cache | @@ -16,6 +16,7 @@ from functools import lru_cache | ||
| 16 | import traceback | 16 | import traceback |
| 17 | import copy | 17 | import copy |
| 18 | from app.util.component.GeometryAdapter import GeometryAdapter | 18 | from app.util.component.GeometryAdapter import GeometryAdapter |
| 19 | +from app.util.component.VacuateConf import VacuateConf | ||
| 19 | class EntryDataVacuate: | 20 | class EntryDataVacuate: |
| 20 | 21 | ||
| 21 | def entry(self,parameter): | 22 | def entry(self,parameter): |
| @@ -317,13 +318,15 @@ class ThisTask: | @@ -317,13 +318,15 @@ class ThisTask: | ||
| 317 | else: | 318 | else: |
| 318 | ext = [round(e, 2) for e in ext] | 319 | ext = [round(e, 2) for e in ext] |
| 319 | 320 | ||
| 321 | + geom_type = GeometryAdapter.get_geometry_type(layer) | ||
| 322 | + | ||
| 320 | extent = "{},{},{},{}".format(ext[0], ext[1], ext[2], ext[3]) | 323 | extent = "{},{},{},{}".format(ext[0], ext[1], ext[2], ext[3]) |
| 321 | table_guid = uuid.uuid1().__str__() | 324 | table_guid = uuid.uuid1().__str__() |
| 322 | table = Table(guid=table_guid, | 325 | table = Table(guid=table_guid, |
| 323 | database_guid=self.database.guid, | 326 | database_guid=self.database.guid, |
| 324 | creator=creator, | 327 | creator=creator, |
| 325 | name=new_layer_name, create_time=this_time, update_time=this_time, | 328 | name=new_layer_name, create_time=this_time, update_time=this_time, |
| 326 | - catalog_guid=self.catalog_guid, table_type=GeometryAdapter.get_table_type(GeometryAdapter.get_geometry_type(layer)), | 329 | + catalog_guid=self.catalog_guid, table_type=GeometryAdapter.get_table_type(geom_type), |
| 327 | extent=extent, | 330 | extent=extent, |
| 328 | feature_count=layer.GetFeatureCount(), | 331 | feature_count=layer.GetFeatureCount(), |
| 329 | is_vacuate=is_vacuate | 332 | is_vacuate=is_vacuate |
| @@ -353,13 +356,16 @@ class ThisTask: | @@ -353,13 +356,16 @@ class ThisTask: | ||
| 353 | # 抽稀表有固定的命名规则 | 356 | # 抽稀表有固定的命名规则 |
| 354 | for level,layer in vacuate_layers.items(): | 357 | for level,layer in vacuate_layers.items(): |
| 355 | pixel_distance_str:str=layer.GetName().split("_")[-1] | 358 | pixel_distance_str:str=layer.GetName().split("_")[-1] |
| 359 | + lev = layer.GetName().split("_")[-2] | ||
| 360 | + | ||
| 356 | if pixel_distance_str.startswith("0"): | 361 | if pixel_distance_str.startswith("0"): |
| 357 | pixel_distance_str="0.{}".format(pixel_distance_str) | 362 | pixel_distance_str="0.{}".format(pixel_distance_str) |
| 358 | 363 | ||
| 359 | pixel_distance = float(pixel_distance_str) | 364 | pixel_distance = float(pixel_distance_str) |
| 365 | + | ||
| 360 | table_vacuate = TableVacuate(guid=uuid.uuid1().__str__(), | 366 | table_vacuate = TableVacuate(guid=uuid.uuid1().__str__(), |
| 361 | table_guid=table_guid, | 367 | table_guid=table_guid, |
| 362 | - level=level, | 368 | + level=int(lev), |
| 363 | name=layer.GetName(), | 369 | name=layer.GetName(), |
| 364 | pixel_distance=pixel_distance) | 370 | pixel_distance=pixel_distance) |
| 365 | self.sys_session.add(table_vacuate) | 371 | self.sys_session.add(table_vacuate) |
| @@ -398,14 +404,18 @@ class VacuateProcess: | @@ -398,14 +404,18 @@ class VacuateProcess: | ||
| 398 | vacuate_layers_gridsize={} | 404 | vacuate_layers_gridsize={} |
| 399 | pg_ds_dict = {} | 405 | pg_ds_dict = {} |
| 400 | # 图层要素大于5W才抽稀 | 406 | # 图层要素大于5W才抽稀 |
| 401 | - least_vacuate_count = 20000 | 407 | + least_vacuate_count = VacuateConf.least_vacuate_count |
| 402 | 408 | ||
| 403 | extent=[] | 409 | extent=[] |
| 404 | is_spatial=False | 410 | is_spatial=False |
| 405 | - # 网格大小是固定的,根据图层的信息滑动选取需要抽稀的等级 | ||
| 406 | - lonlat_gridsize=[0.000075,0.00015,0.0003,0.0006,0.0012,0.0024,0.0048,0.0096,0.0192,0.0384,0.0768] | ||
| 407 | - project_gridsize=[15,30,60,120,240,480,960,1920,3840,7680] | ||
| 408 | 411 | ||
| 412 | + lonlat_gridsize = VacuateConf.lonlat_gridsize | ||
| 413 | + project_gridsize = VacuateConf.project_gridsize | ||
| 414 | + | ||
| 415 | + # 该抽稀过程使用的grid_size | ||
| 416 | + t_grid_size = [] | ||
| 417 | + | ||
| 418 | + # 该抽稀过程的抽稀网格 | ||
| 409 | this_gridsize=[] | 419 | this_gridsize=[] |
| 410 | 420 | ||
| 411 | 421 | ||
| @@ -453,17 +463,17 @@ class VacuateProcess: | @@ -453,17 +463,17 @@ class VacuateProcess: | ||
| 453 | ###### | 463 | ###### |
| 454 | 464 | ||
| 455 | if extent[0]>180: | 465 | if extent[0]>180: |
| 456 | - t_grid_size=self.project_gridsize | 466 | + self.t_grid_size=self.project_gridsize |
| 457 | else: | 467 | else: |
| 458 | - t_grid_size = self.lonlat_gridsize | ||
| 459 | - for grid_size in t_grid_size: | 468 | + self.t_grid_size = self.lonlat_gridsize |
| 469 | + for grid_size in self.t_grid_size: | ||
| 460 | # 最少抽稀个数 | 470 | # 最少抽稀个数 |
| 461 | - if lc>self.least_vacuate_count: | 471 | + if lc > self.least_vacuate_count: |
| 462 | # 网格数至少大于 | 472 | # 网格数至少大于 |
| 463 | - if ((extent[1] - extent[0])*(extent[3] - extent[2]))/(grid_size**2)>self.least_vacuate_count: | 473 | + if ((extent[1] - extent[0]) * (extent[3] - extent[2])) / (grid_size**2)>self.least_vacuate_count: |
| 464 | # 要素数量大于网格数量 | 474 | # 要素数量大于网格数量 |
| 465 | # 要考虑图层的疏密程度,original_density*(100.0/fill_precent) 为疏密指数 | 475 | # 要考虑图层的疏密程度,original_density*(100.0/fill_precent) 为疏密指数 |
| 466 | - if lc*original_density*(100.0/fill_precent)>((extent[1] - extent[0])*(extent[3] - extent[2]))/(grid_size**2) : | 476 | + if lc * original_density * (100.0/fill_precent)>((extent[1] - extent[0])*(extent[3] - extent[2]))/(grid_size**2) : |
| 467 | print(grid_size) | 477 | print(grid_size) |
| 468 | self.this_gridsize.append(grid_size) | 478 | self.this_gridsize.append(grid_size) |
| 469 | self.max_level += 1 | 479 | self.max_level += 1 |
| @@ -479,6 +489,7 @@ class VacuateProcess: | @@ -479,6 +489,7 @@ class VacuateProcess: | ||
| 479 | # 生成抽稀图层 | 489 | # 生成抽稀图层 |
| 480 | options = options[1:] | 490 | options = options[1:] |
| 481 | options.append("OVERWRITE=yes") | 491 | options.append("OVERWRITE=yes") |
| 492 | + options.append("LAUNDER=no") | ||
| 482 | for l in range(self.max_level): | 493 | for l in range(self.max_level): |
| 483 | this_grid_len = self.this_gridsize[l] | 494 | this_grid_len = self.this_gridsize[l] |
| 484 | 495 | ||
| @@ -496,7 +507,8 @@ class VacuateProcess: | @@ -496,7 +507,8 @@ class VacuateProcess: | ||
| 496 | # 抽稀表有固定的命名规则 | 507 | # 抽稀表有固定的命名规则 |
| 497 | # 抽稀表一定要覆盖 | 508 | # 抽稀表一定要覆盖 |
| 498 | 509 | ||
| 499 | - vl = pg.CreateLayer("{}_vacuate_{}_{}".format(new_layer_name, l, grid_name), layer.GetSpatialRef(), | 510 | + |
| 511 | + vl = pg.CreateLayer("{}_vacuate_{}_{}".format(new_layer_name, self.t_grid_size.index(this_grid_len), grid_name), layer.GetSpatialRef(), | ||
| 500 | ogr.wkbUnknown, options) | 512 | ogr.wkbUnknown, options) |
| 501 | # 抽稀表不需要属性 | 513 | # 抽稀表不需要属性 |
| 502 | # vl.CreateFields(schema) | 514 | # vl.CreateFields(schema) |
| @@ -5,8 +5,6 @@ | @@ -5,8 +5,6 @@ | ||
| 5 | from osgeo import ogr | 5 | from osgeo import ogr |
| 6 | from sqlalchemy import create_engine | 6 | from sqlalchemy import create_engine |
| 7 | from sqlalchemy.orm import sessionmaker,Session | 7 | from sqlalchemy.orm import sessionmaker,Session |
| 8 | -from sqlalchemy.engine import ResultProxy | ||
| 9 | - | ||
| 10 | class PGUtil: | 8 | class PGUtil: |
| 11 | 9 | ||
| 12 | @classmethod | 10 | @classmethod |
| @@ -27,11 +25,6 @@ class PGUtil: | @@ -27,11 +25,6 @@ class PGUtil: | ||
| 27 | 25 | ||
| 28 | @classmethod | 26 | @classmethod |
| 29 | def get_info_from_sqlachemy_uri(cls,uri): | 27 | def get_info_from_sqlachemy_uri(cls,uri): |
| 30 | - ''' | ||
| 31 | - 解析sqlachemy_uri | ||
| 32 | - :param uri: | ||
| 33 | - :return: | ||
| 34 | - ''' | ||
| 35 | parts = uri.split(":") | 28 | parts = uri.split(":") |
| 36 | user = parts[1][2:] | 29 | user = parts[1][2:] |
| 37 | 30 | ||
| @@ -56,12 +49,7 @@ class PGUtil: | @@ -56,12 +49,7 @@ class PGUtil: | ||
| 56 | 49 | ||
| 57 | @classmethod | 50 | @classmethod |
| 58 | def get_geo_column(cls,table_name,db_session): | 51 | def get_geo_column(cls,table_name,db_session): |
| 59 | - ''' | ||
| 60 | # 判断空间列 | 52 | # 判断空间列 |
| 61 | - :param table_name: | ||
| 62 | - :param db_session: | ||
| 63 | - :return: | ||
| 64 | - ''' | ||
| 65 | geom_col_sql = ''' | 53 | geom_col_sql = ''' |
| 66 | SELECT a.attname AS field,t.typname AS type | 54 | SELECT a.attname AS field,t.typname AS type |
| 67 | FROM | 55 | FROM |
| @@ -75,7 +63,7 @@ class PGUtil: | @@ -75,7 +63,7 @@ class PGUtil: | ||
| 75 | and a.atttypid = t.oid | 63 | and a.atttypid = t.oid |
| 76 | '''.format(table_name) | 64 | '''.format(table_name) |
| 77 | geom_col = None | 65 | geom_col = None |
| 78 | - geom_result: ResultProxy = db_session.execute(geom_col_sql) | 66 | + geom_result = db_session.execute(geom_col_sql) |
| 79 | for row_proxy in geom_result: | 67 | for row_proxy in geom_result: |
| 80 | if row_proxy[1].__eq__("geometry"): | 68 | if row_proxy[1].__eq__("geometry"): |
| 81 | geom_col = row_proxy[0] | 69 | geom_col = row_proxy[0] |
| @@ -84,39 +72,39 @@ class PGUtil: | @@ -84,39 +72,39 @@ class PGUtil: | ||
| 84 | 72 | ||
| 85 | @classmethod | 73 | @classmethod |
| 86 | def get_table_count(cls,table_name,db_session): | 74 | def get_table_count(cls,table_name,db_session): |
| 87 | - ''' | ||
| 88 | - 获取图层数量 | ||
| 89 | - :param table_name: | ||
| 90 | - :param db_session: | ||
| 91 | - :return: | ||
| 92 | - ''' | ||
| 93 | count_result = db_session.execute('''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format( | 75 | count_result = db_session.execute('''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format( |
| 94 | table_name)).fetchone() | 76 | table_name)).fetchone() |
| 95 | count = count_result[0] | 77 | count = count_result[0] |
| 96 | if count< 1000000: | 78 | if count< 1000000: |
| 97 | - count_result: ResultProxy = db_session.execute('select count(*) from "{}"'.format(table_name)).fetchone() | 79 | + count_result = db_session.execute('select count(*) from "{}"'.format(table_name)).fetchone() |
| 98 | count=count_result[0] | 80 | count=count_result[0] |
| 99 | return count | 81 | return count |
| 100 | 82 | ||
| 101 | @classmethod | 83 | @classmethod |
| 102 | - def check_space(cls, sqlachemy_uri): | 84 | + def check_table_privilege(cls,table_name,pri_type,user,pg_ds): |
| 103 | ''' | 85 | ''' |
| 104 | - 判断数据库是否为空间库 | ||
| 105 | - :param sqlachemy_uri: | 86 | + 通过pg_ds来判断用户是否对表具有权限 |
| 87 | + :param table_name: | ||
| 88 | + :param pri_type: | ||
| 89 | + :param user: | ||
| 90 | + :param pg_ds: | ||
| 106 | :return: | 91 | :return: |
| 107 | ''' | 92 | ''' |
| 108 | - system_session = None | ||
| 109 | - check = True | ||
| 110 | - try: | ||
| 111 | - test_sql = "select st_geometryfromtext('POINT(1 1)')" | ||
| 112 | - engine = create_engine(sqlachemy_uri) | ||
| 113 | - system_session = sessionmaker(bind=engine)() | ||
| 114 | - system_session.execute(test_sql).fetchone() | ||
| 115 | - except: | ||
| 116 | - check = False | ||
| 117 | - finally: | ||
| 118 | - if system_session: | ||
| 119 | - system_session.close() | ||
| 120 | - | ||
| 121 | - return check | ||
| 122 | 93 | ||
| 94 | + pri = pg_ds.ExecuteSQL("select * from information_schema.table_privileges " | ||
| 95 | + "where grantee='{}' and table_name='{}' and privilege_type='{}' " | ||
| 96 | + .format(user,table_name,pri_type)) | ||
| 97 | + | ||
| 98 | + if pri.GetNextFeature(): | ||
| 99 | + return True | ||
| 100 | + else: | ||
| 101 | + return False | ||
| 102 | + | ||
| 103 | + | ||
| 104 | + @classmethod | ||
| 105 | + def check_database_privilege(cls,table_name,pri_type,user,session): | ||
| 106 | + pass | ||
| 107 | + | ||
| 108 | + @classmethod | ||
| 109 | + def check_database_privilege(cls,table_name,pri_type,user,session): | ||
| 110 | + pass |
| @@ -8,11 +8,45 @@ class SQLUtil: | @@ -8,11 +8,45 @@ class SQLUtil: | ||
| 8 | 8 | ||
| 9 | 9 | ||
| 10 | @classmethod | 10 | @classmethod |
| 11 | - def get_count(cls,session,table_name): | ||
| 12 | - count = session.execute('select count(*) from "{}"'.format(table_name)).fetchone()[0] | 11 | + def get_table_count(cls,table_name,db_session): |
| 12 | + count_result = db_session.execute('''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format( | ||
| 13 | + table_name)).fetchone() | ||
| 14 | + count = count_result[0] | ||
| 15 | + if count< 1000000: | ||
| 16 | + count_result = db_session.execute('select count(*) from "{}"'.format(table_name)).fetchone() | ||
| 17 | + count=count_result[0] | ||
| 13 | return count | 18 | return count |
| 14 | 19 | ||
| 15 | @classmethod | 20 | @classmethod |
| 16 | def rename(cls,session,origin,after_name): | 21 | def rename(cls,session,origin,after_name): |
| 17 | rename_sql = 'alter table "{}" rename to "{}"'.format(origin, after_name) | 22 | rename_sql = 'alter table "{}" rename to "{}"'.format(origin, after_name) |
| 18 | session.execute(rename_sql) | 23 | session.execute(rename_sql) |
| 24 | + session.commit() | ||
| 25 | + | ||
| 26 | + @classmethod | ||
| 27 | + def check_table_privilege(cls,table_name,pri_type,user,session): | ||
| 28 | + ''' | ||
| 29 | + 判断用户是否对表具有权限 | ||
| 30 | + :param table_name: | ||
| 31 | + :param pri_type: | ||
| 32 | + :param user: | ||
| 33 | + :param pg_ds: | ||
| 34 | + :return: | ||
| 35 | + ''' | ||
| 36 | + pri = session.execute("select * from information_schema.table_privileges " | ||
| 37 | + "where grantee='{}' and table_name='{}' and privilege_type='{}' " | ||
| 38 | + .format(user,table_name,pri_type)).fetchall() | ||
| 39 | + if len(pri) == 1: | ||
| 40 | + return True | ||
| 41 | + else: | ||
| 42 | + return False | ||
| 43 | + | ||
| 44 | + | ||
| 45 | + | ||
| 46 | + @classmethod | ||
| 47 | + def check_database_privilege(cls,table_name,pri_type,user,session): | ||
| 48 | + pass | ||
| 49 | + | ||
| 50 | + @classmethod | ||
| 51 | + def check_database_privilege_pg(cls,table_name,pri_type,user,session): | ||
| 52 | + pass |
app/util/component/VacuateConf.py
0 → 100644
| 1 | +# coding=utf-8 | ||
| 2 | +#author: 4N | ||
| 3 | +#createtime: 2021/8/25 | ||
| 4 | +#email: nheweijun@sina.com | ||
| 5 | + | ||
| 6 | + | ||
| 7 | +class VacuateConf: | ||
| 8 | + least_vacuate_count = 20000 | ||
| 9 | + lonlat_gridsize = [0.00008, 0.00016, 0.00032, 0.00064, 0.00128, 0.00256, 0.00512, 0.01024, 0.02048,0.04096, 0.08192] | ||
| 10 | + project_gridsize = [8,16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192] |
| 1 | -LoadModule wsgi_module "/usr/lib/apache2/modules/mod_wsgi-py39.cpython-39-x86_64-linux-gnu.so" | ||
| 2 | - "/usr" | ||
| 3 | - | ||
| 4 | - conf.d/*.conf | ||
| 5 | -<VirtualHost *> | ||
| 6 | - ServerName dampmanager | ||
| 7 | - WSGIDaemonProcess yourapplication user=chinadci group=chinadci threads=5 | ||
| 8 | - WSGIScriptAlias /DMapManager /usr/src/DMapManager/run.wsgi | ||
| 9 | - <Directory /usr/src/> | ||
| 10 | - WSGIProcessGroup yourapplication | ||
| 11 | - WSGIApplicationGroup %{GLOBAL} | ||
| 12 | - Require all granted | ||
| 13 | - </Directory> | ||
| 14 | -</VirtualHost> | ||
| 15 | - | ||
| 16 | -<virtualhost *:80> | ||
| 17 | - ServerName dampmanager | ||
| 18 | - WSGIDaemonProcess mlfans threads=5 | ||
| 19 | - WSGIScriptAlias / /var/www/mlfans/app.wsgi | ||
| 20 | - | ||
| 21 | - <directory /var/www/mlfans> | ||
| 22 | - WSGIProcessGroup mlfans | ||
| 23 | - WSGIApplicationGroup %{GLOBAL} | ||
| 24 | - WSGIScriptReloading On | ||
| 25 | - Order deny,allow | ||
| 26 | - Allow from all | ||
| 27 | - </directory> | ||
| 28 | -</virtualhost> | ||
| 29 | - | ||
| 30 | - | ||
| 31 | - | ||
| 32 | - | ||
| 33 | -LoadModule wsgi_module "/usr/lib/apache2/modules/mod_wsgi-py39.cpython-39-x86_64-linux-gnu.so" | ||
| 34 | -WSGIPythonHome "/usr" | ||
| 35 | - | ||
| 36 | -WSGIScriptAlias /DMapManager /usr/DMapManager/run.wsgi | ||
| 37 | -<Directory /usr/> | ||
| 38 | - Require all granted | ||
| 39 | -</Directory> | ||
| 1 | +# | ||
| 2 | +# This is the main Apache HTTP server configuration file. It contains the | ||
| 3 | +# configuration directives that give the server its instructions. | ||
| 4 | +# See <URL:http://httpd.apache.org/docs/2.4/> for detailed information. | ||
| 5 | +# In particular, see | ||
| 6 | +# <URL:http://httpd.apache.org/docs/2.4/mod/directives.html> | ||
| 7 | +# for a discussion of each configuration directive. | ||
| 8 | +# | ||
| 9 | +# Do NOT simply read the instructions in here without understanding | ||
| 10 | +# what they do. They're here only as hints or reminders. If you are unsure | ||
| 11 | +# consult the online docs. You have been warned. | ||
| 12 | +# | ||
| 13 | +# Configuration and logfile names: If the filenames you specify for many | ||
| 14 | +# of the server's control files begin with "/" (or "drive:/" for Win32), the | ||
| 15 | +# server will use that explicit path. If the filenames do *not* begin | ||
| 16 | +# with "/", the value of ServerRoot is prepended -- so 'log/access_log' | ||
| 17 | +# with ServerRoot set to '/www' will be interpreted by the | ||
| 18 | +# server as '/www/log/access_log', where as '/log/access_log' will be | ||
| 19 | +# interpreted as '/log/access_log'. | ||
| 20 | + | ||
| 21 | +# | ||
| 22 | +# ServerRoot: The top of the directory tree under which the server's | ||
| 23 | +# configuration, error, and log files are kept. | ||
| 24 | +# | ||
| 25 | +# Do not add a slash at the end of the directory path. If you point | ||
| 26 | +# ServerRoot at a non-local disk, be sure to specify a local disk on the | ||
| 27 | +# Mutex directive, if file-based mutexes are used. If you wish to share the | ||
| 28 | +# same ServerRoot for multiple httpd daemons, you will need to change at | ||
| 29 | +# least PidFile. | ||
| 30 | +# | ||
| 31 | +ServerRoot "/etc/httpd" | ||
| 32 | + | ||
| 33 | +# | ||
| 34 | +# Listen: Allows you to bind Apache to specific IP addresses and/or | ||
| 35 | +# ports, instead of the default. See also the <VirtualHost> | ||
| 36 | +# directive. | ||
| 37 | +# | ||
| 38 | +# Change this to Listen on specific IP addresses as shown below to | ||
| 39 | +# prevent Apache from glomming onto all bound IP addresses. | ||
| 40 | +# | ||
| 41 | +#Listen 12.34.56.78:80 | ||
| 42 | +Listen 80 | ||
| 43 | + | ||
| 44 | +# | ||
| 45 | +# Dynamic Shared Object (DSO) Support | ||
| 46 | +# | ||
| 47 | +# To be able to use the functionality of a module which was built as a DSO you | ||
| 48 | +# have to place corresponding `LoadModule' lines at this location so the | ||
| 49 | +# directives contained in it are actually available _before_ they are used. | ||
| 50 | +# Statically compiled modules (those listed by `httpd -l') do not need | ||
| 51 | +# to be loaded here. | ||
| 52 | +# | ||
| 53 | +# Example: | ||
| 54 | +# LoadModule foo_module modules/mod_foo.so | ||
| 55 | +# | ||
| 56 | +Include conf.modules.d/*.conf | ||
| 57 | + | ||
| 58 | +# | ||
| 59 | +# If you wish httpd to run as a different user or group, you must run | ||
| 60 | +# httpd as root initially and it will switch. | ||
| 61 | +# | ||
| 62 | +# User/Group: The name (or #number) of the user/group to run httpd as. | ||
| 63 | +# It is usually good practice to create a dedicated user and group for | ||
| 64 | +# running httpd, as with most system services. | ||
| 65 | +# | ||
| 66 | +User apache | ||
| 67 | +Group apache | ||
| 68 | + | ||
| 69 | +# 'Main' server configuration | ||
| 70 | +# | ||
| 71 | +# The directives in this section set up the values used by the 'main' | ||
| 72 | +# server, which responds to any requests that aren't handled by a | ||
| 73 | +# <VirtualHost> definition. These values also provide defaults for | ||
| 74 | +# any <VirtualHost> containers you may define later in the file. | ||
| 75 | +# | ||
| 76 | +# All of these directives may appear inside <VirtualHost> containers, | ||
| 77 | +# in which case these default settings will be overridden for the | ||
| 78 | +# virtual host being defined. | ||
| 79 | +# | ||
| 80 | + | ||
| 81 | +# | ||
| 82 | +# ServerAdmin: Your address, where problems with the server should be | ||
| 83 | +# e-mailed. This address appears on some server-generated pages, such | ||
| 84 | +# as error documents. e.g. admin@your-domain.com | ||
| 85 | +# | ||
| 86 | +ServerAdmin root@localhost | ||
| 87 | + | ||
| 88 | +# | ||
| 89 | +# ServerName gives the name and port that the server uses to identify itself. | ||
| 90 | +# This can often be determined automatically, but we recommend you specify | ||
| 91 | +# it explicitly to prevent problems during startup. | ||
| 92 | +# | ||
| 93 | +# If your host doesn't have a registered DNS name, enter its IP address here. | ||
| 94 | +# | ||
| 95 | +#ServerName www.example.com:80 | ||
| 96 | + | ||
| 97 | +# | ||
| 98 | +# Deny access to the entirety of your server's filesystem. You must | ||
| 99 | +# explicitly permit access to web content directories in other | ||
| 100 | +# <Directory> blocks below. | ||
| 101 | +# | ||
| 102 | +<Directory /> | ||
| 103 | + AllowOverride none | ||
| 104 | + Require all denied | ||
| 105 | +</Directory> | ||
| 106 | + | ||
| 107 | +# | ||
| 108 | +# Note that from this point forward you must specifically allow | ||
| 109 | +# particular features to be enabled - so if something's not working as | ||
| 110 | +# you might expect, make sure that you have specifically enabled it | ||
| 111 | +# below. | ||
| 112 | +# | ||
| 113 | + | ||
| 114 | +# | ||
| 115 | +# DocumentRoot: The directory out of which you will serve your | ||
| 116 | +# documents. By default, all requests are taken from this directory, but | ||
| 117 | +# symbolic links and aliases may be used to point to other locations. | ||
| 118 | +# | ||
| 119 | +DocumentRoot "/var/www/html" | ||
| 120 | + | ||
| 121 | +# | ||
| 122 | +# Relax access to content within /var/www. | ||
| 123 | +# | ||
| 124 | +<Directory "/var/www"> | ||
| 125 | + AllowOverride None | ||
| 126 | + # Allow open access: | ||
| 127 | + Require all granted | ||
| 128 | +</Directory> | ||
| 129 | + | ||
| 130 | +# Further relax access to the default document root: | ||
| 131 | +<Directory "/var/www/html"> | ||
| 132 | + # | ||
| 133 | + # Possible values for the Options directive are "None", "All", | ||
| 134 | + # or any combination of: | ||
| 135 | + # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews | ||
| 136 | + # | ||
| 137 | + # Note that "MultiViews" must be named *explicitly* --- "Options All" | ||
| 138 | + # doesn't give it to you. | ||
| 139 | + # | ||
| 140 | + # The Options directive is both complicated and important. Please see | ||
| 141 | + # http://httpd.apache.org/docs/2.4/mod/core.html#options | ||
| 142 | + # for more information. | ||
| 143 | + # | ||
| 144 | + Options Indexes FollowSymLinks | ||
| 145 | + | ||
| 146 | + # | ||
| 147 | + # AllowOverride controls what directives may be placed in .htaccess files. | ||
| 148 | + # It can be "All", "None", or any combination of the keywords: | ||
| 149 | + # Options FileInfo AuthConfig Limit | ||
| 150 | + # | ||
| 151 | + AllowOverride None | ||
| 152 | + | ||
| 153 | + # | ||
| 154 | + # Controls who can get stuff from this server. | ||
| 155 | + # | ||
| 156 | + Require all granted | ||
| 157 | +</Directory> | ||
| 158 | + | ||
| 159 | +# | ||
| 160 | +# DirectoryIndex: sets the file that Apache will serve if a directory | ||
| 161 | +# is requested. | ||
| 162 | +# | ||
| 163 | +<IfModule dir_module> | ||
| 164 | + DirectoryIndex index.html | ||
| 165 | +</IfModule> | ||
| 166 | + | ||
| 167 | +# | ||
| 168 | +# The following lines prevent .htaccess and .htpasswd files from being | ||
| 169 | +# viewed by Web clients. | ||
| 170 | +# | ||
| 171 | +<Files ".ht*"> | ||
| 172 | + Require all denied | ||
| 173 | +</Files> | ||
| 174 | + | ||
| 175 | +# | ||
| 176 | +# ErrorLog: The location of the error log file. | ||
| 177 | +# If you do not specify an ErrorLog directive within a <VirtualHost> | ||
| 178 | +# container, error messages relating to that virtual host will be | ||
| 179 | +# logged here. If you *do* define an error logfile for a <VirtualHost> | ||
| 180 | +# container, that host's errors will be logged there and not here. | ||
| 181 | +# | ||
| 182 | +ErrorLog "logs/error_log" | ||
| 183 | + | ||
| 184 | +# | ||
| 185 | +# LogLevel: Control the number of messages logged to the error_log. | ||
| 186 | +# Possible values include: debug, info, notice, warn, error, crit, | ||
| 187 | +# alert, emerg. | ||
| 188 | +# | ||
| 189 | +LogLevel warn | ||
| 190 | + | ||
| 191 | +<IfModule log_config_module> | ||
| 192 | + # | ||
| 193 | + # The following directives define some format nicknames for use with | ||
| 194 | + # a CustomLog directive (see below). | ||
| 195 | + # | ||
| 196 | + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined | ||
| 197 | + LogFormat "%h %l %u %t \"%r\" %>s %b" common | ||
| 198 | + | ||
| 199 | + <IfModule logio_module> | ||
| 200 | + # You need to enable mod_logio.c to use %I and %O | ||
| 201 | + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio | ||
| 202 | + </IfModule> | ||
| 203 | + | ||
| 204 | + # | ||
| 205 | + # The location and format of the access logfile (Common Logfile Format). | ||
| 206 | + # If you do not define any access logfiles within a <VirtualHost> | ||
| 207 | + # container, they will be logged here. Contrariwise, if you *do* | ||
| 208 | + # define per-<VirtualHost> access logfiles, transactions will be | ||
| 209 | + # logged therein and *not* in this file. | ||
| 210 | + # | ||
| 211 | + #CustomLog "logs/access_log" common | ||
| 212 | + | ||
| 213 | + # | ||
| 214 | + # If you prefer a logfile with access, agent, and referer information | ||
| 215 | + # (Combined Logfile Format) you can use the following directive. | ||
| 216 | + # | ||
| 217 | + CustomLog "logs/access_log" combined | ||
| 218 | +</IfModule> | ||
| 219 | + | ||
| 220 | +<IfModule alias_module> | ||
| 221 | + # | ||
| 222 | + # Redirect: Allows you to tell clients about documents that used to | ||
| 223 | + # exist in your server's namespace, but do not anymore. The client | ||
| 224 | + # will make a new request for the document at its new location. | ||
| 225 | + # Example: | ||
| 226 | + # Redirect permanent /foo http://www.example.com/bar | ||
| 227 | + | ||
| 228 | + # | ||
| 229 | + # Alias: Maps web paths into filesystem paths and is used to | ||
| 230 | + # access content that does not live under the DocumentRoot. | ||
| 231 | + # Example: | ||
| 232 | + # Alias /webpath /full/filesystem/path | ||
| 233 | + # | ||
| 234 | + # If you include a trailing / on /webpath then the server will | ||
| 235 | + # require it to be present in the URL. You will also likely | ||
| 236 | + # need to provide a <Directory> section to allow access to | ||
| 237 | + # the filesystem path. | ||
| 238 | + | ||
| 239 | + # | ||
| 240 | + # ScriptAlias: This controls which directories contain server scripts. | ||
| 241 | + # ScriptAliases are essentially the same as Aliases, except that | ||
| 242 | + # documents in the target directory are treated as applications and | ||
| 243 | + # run by the server when requested rather than as documents sent to the | ||
| 244 | + # client. The same rules about trailing "/" apply to ScriptAlias | ||
| 245 | + # directives as to Alias. | ||
| 246 | + # | ||
| 247 | + ScriptAlias /cgi-bin/ "/var/www/cgi-bin/" | ||
| 248 | + | ||
| 249 | +</IfModule> | ||
| 250 | + | ||
| 251 | +# | ||
| 252 | +# "/var/www/cgi-bin" should be changed to whatever your ScriptAliased | ||
| 253 | +# CGI directory exists, if you have that configured. | ||
| 254 | +# | ||
| 255 | +<Directory "/var/www/cgi-bin"> | ||
| 256 | + AllowOverride None | ||
| 257 | + Options None | ||
| 258 | + Require all granted | ||
| 259 | +</Directory> | ||
| 260 | + | ||
| 261 | +<IfModule mime_module> | ||
| 262 | + # | ||
| 263 | + # TypesConfig points to the file containing the list of mappings from | ||
| 264 | + # filename extension to MIME-type. | ||
| 265 | + # | ||
| 266 | + TypesConfig /etc/mime.types | ||
| 267 | + | ||
| 268 | + # | ||
| 269 | + # AddType allows you to add to or override the MIME configuration | ||
| 270 | + # file specified in TypesConfig for specific file types. | ||
| 271 | + # | ||
| 272 | + #AddType application/x-gzip .tgz | ||
| 273 | + # | ||
| 274 | + # AddEncoding allows you to have certain browsers uncompress | ||
| 275 | + # information on the fly. Note: Not all browsers support this. | ||
| 276 | + # | ||
| 277 | + #AddEncoding x-compress .Z | ||
| 278 | + #AddEncoding x-gzip .gz .tgz | ||
| 279 | + # | ||
| 280 | + # If the AddEncoding directives above are commented-out, then you | ||
| 281 | + # probably should define those extensions to indicate media types: | ||
| 282 | + # | ||
| 283 | + AddType application/x-compress .Z | ||
| 284 | + AddType application/x-gzip .gz .tgz | ||
| 285 | + | ||
| 286 | + # | ||
| 287 | + # AddHandler allows you to map certain file extensions to "handlers": | ||
| 288 | + # actions unrelated to filetype. These can be either built into the server | ||
| 289 | + # or added with the Action directive (see below) | ||
| 290 | + # | ||
| 291 | + # To use CGI scripts outside of ScriptAliased directories: | ||
| 292 | + # (You will also need to add "ExecCGI" to the "Options" directive.) | ||
| 293 | + # | ||
| 294 | + #AddHandler cgi-script .cgi | ||
| 295 | + | ||
| 296 | + # For type maps (negotiated resources): | ||
| 297 | + #AddHandler type-map var | ||
| 298 | + | ||
| 299 | + # | ||
| 300 | + # Filters allow you to process content before it is sent to the client. | ||
| 301 | + # | ||
| 302 | + # To parse .shtml files for server-side includes (SSI): | ||
| 303 | + # (You will also need to add "Includes" to the "Options" directive.) | ||
| 304 | + # | ||
| 305 | + AddType text/html .shtml | ||
| 306 | + AddOutputFilter INCLUDES .shtml | ||
| 307 | +</IfModule> | ||
| 308 | + | ||
| 309 | +# | ||
| 310 | +# Specify a default charset for all content served; this enables | ||
| 311 | +# interpretation of all content as UTF-8 by default. To use the | ||
| 312 | +# default browser choice (ISO-8859-1), or to allow the META tags | ||
| 313 | +# in HTML content to override this choice, comment out this | ||
| 314 | +# directive: | ||
| 315 | +# | ||
| 316 | +AddDefaultCharset UTF-8 | ||
| 317 | + | ||
| 318 | +<IfModule mime_magic_module> | ||
| 319 | + # | ||
| 320 | + # The mod_mime_magic module allows the server to use various hints from the | ||
| 321 | + # contents of the file itself to determine its type. The MIMEMagicFile | ||
| 322 | + # directive tells the module where the hint definitions are located. | ||
| 323 | + # | ||
| 324 | + conf/magic | ||
| 325 | +</IfModule> | ||
| 326 | + | ||
| 327 | +# | ||
| 328 | +# Customizable error responses come in three flavors: | ||
| 329 | +# 1) plain text 2) local redirects 3) external redirects | ||
| 330 | +# | ||
| 331 | +# Some examples: | ||
| 332 | +#ErrorDocument 500 "The server made a boo boo." | ||
| 333 | +#ErrorDocument 404 /missing.html | ||
| 334 | +#ErrorDocument 404 "/cgi-bin/missing_handler.pl" | ||
| 335 | +#ErrorDocument 402 http://www.example.com/subscription_info.html | ||
| 336 | +# | ||
| 337 | + | ||
| 338 | +# | ||
| 339 | +# EnableMMAP and EnableSendfile: On systems that support it, | ||
| 340 | +# memory-mapping or the sendfile syscall may be used to deliver | ||
| 341 | +# files. This usually improves server performance, but must | ||
| 342 | +# be turned off when serving from networked-mounted | ||
| 343 | +# filesystems or if support for these functions is otherwise | ||
| 344 | +# broken on your system. | ||
| 345 | +# Defaults if commented: EnableMMAP On, EnableSendfile Off | ||
| 346 | +# | ||
| 347 | +#EnableMMAP off | ||
| 348 | +EnableSendfile on | ||
| 349 | + | ||
| 350 | +# Supplemental configuration | ||
| 351 | +# | ||
| 352 | +# Load config files in the "/etc/httpd/conf.d" directory, if any. | ||
| 353 | + conf.d/*.conf | ||
| 354 | + | ||
| 355 | +LoadModule wsgi_module "/usr/lib64/httpd/modules/mod_wsgi-py37.cpython-37m-x86_64-linux-gnu.so" | ||
| 356 | + "/var/gdal" | ||
| 357 | + | ||
| 358 | + / /usr/src/app/run.wsgi | ||
| 359 | +<Directory /usr/> | ||
| 360 | + Require all granted | ||
| 361 | +</Directory> |
run.apache.sh
0 → 100644
| 1 | +#! /bin/sh | ||
| 2 | + | ||
| 3 | +#停止容器 | ||
| 4 | +echo "正在关闭容器..." | ||
| 5 | +docker stop dmapmanager | ||
| 6 | +docker rm dmapmanager | ||
| 7 | + | ||
| 8 | +curPath=$(readlink -f $(dirname $0)) | ||
| 9 | + | ||
| 10 | + | ||
| 11 | +#设置日志权限 | ||
| 12 | +chmod -R 777 $curPath/logs/* | ||
| 13 | + | ||
| 14 | +#设置端口 | ||
| 15 | +port="" | ||
| 16 | +if [ ! -n "$1" ] ;then | ||
| 17 | +port="8840" | ||
| 18 | +echo "未设置端口,使用默认8840端口..." | ||
| 19 | +else | ||
| 20 | +port=$1 | ||
| 21 | +echo "端口设置为$1 ..." | ||
| 22 | +fi | ||
| 23 | + | ||
| 24 | +#启动容器和apache | ||
| 25 | +echo "正在启动容器..." | ||
| 26 | +set="--privileged=true -e TZ="Asia/Shanghai" --restart=always -e ALLOW_IP_RANGE=0.0.0.0/0" | ||
| 27 | +docker run -d --name dmapmanager $set -p $port:80 -v $curPath:/usr/src/app -v $curPath/httpd.conf:/etc/httpd/conf/httpd.conf dci/dmapdms:4.0 /usr/sbin/init | ||
| 28 | +docker exec -d dmapmanager systemctl start httpd | ||
| 29 | +sleep 5 | ||
| 30 | +curl localhost:$port/release |
run.wsgi.docker.sh
deleted
100644 → 0
| 1 | -#! /bin/sh | ||
| 2 | - | ||
| 3 | -#停止容器 | ||
| 4 | -echo "正在关闭容器..." | ||
| 5 | -docker stop apache | ||
| 6 | -docker rm apache | ||
| 7 | - | ||
| 8 | -curPath=$(readlink -f $(dirname $0)) | ||
| 9 | - | ||
| 10 | -#寻找模块 | ||
| 11 | -echo "在modules下寻找模块..." | ||
| 12 | -map="" | ||
| 13 | -for mod in $(ls $curPath/modules) | ||
| 14 | -do | ||
| 15 | - map="$map -v $curPath/modules/$mod:/usr/src/$mod" | ||
| 16 | -done | ||
| 17 | - | ||
| 18 | -#设置日志权限 | ||
| 19 | -for mod in $(ls $curPath/modules) | ||
| 20 | -do | ||
| 21 | - chmod -R 777 $curPath/modules/$mod/logs/* | ||
| 22 | -done | ||
| 23 | - | ||
| 24 | - | ||
| 25 | -#设置端口 | ||
| 26 | -port="" | ||
| 27 | -if [ ! -n "$1" ] ;then | ||
| 28 | - port="8888" | ||
| 29 | - echo "未设置端口,使用默认8888端口..." | ||
| 30 | -else | ||
| 31 | - port=$1 | ||
| 32 | - echo "端口设置为$1 ..." | ||
| 33 | -fi | ||
| 34 | - | ||
| 35 | -#修改httpd.conf | ||
| 36 | -echo "正在修改httpd.conf..." | ||
| 37 | -rm $curPath/httpd.conf | ||
| 38 | -cp $curPath/httpd.conf.sample $curPath/httpd.conf | ||
| 39 | -echo "<VirtualHost *>" >> $curPath/httpd.conf | ||
| 40 | -echo " ServerName apacheflask">>$curPath/httpd.conf | ||
| 41 | -echo " WSGIDaemonProcess yourapplication user=chinadci group=chinadci threads=5">>$curPath/httpd.conf | ||
| 42 | - | ||
| 43 | -for mod in $(ls $curPath/modules) | ||
| 44 | -do | ||
| 45 | - echo " WSGIScriptAlias /$mod /usr/src/$mod/run.wsgi">>$curPath/httpd.conf | ||
| 46 | -done | ||
| 47 | - | ||
| 48 | -echo " <Directory /usr/src/app>">>$curPath/httpd.conf | ||
| 49 | -echo " WSGIProcessGroup yourapplication">>$curPath/httpd.conf | ||
| 50 | -echo " WSGIApplicationGroup %{GLOBAL}">>$curPath/httpd.conf | ||
| 51 | -echo " Require all granted">>$curPath/httpd.conf | ||
| 52 | -echo " </Directory>">>$curPath/httpd.conf | ||
| 53 | -echo "</VirtualHost>">>$curPath/httpd.conf | ||
| 54 | - | ||
| 55 | -#启动容器和apache | ||
| 56 | -echo "正在启动容器..." | ||
| 57 | -set="--privileged=true -e TZ="Asia/Shanghai" --restart=always -e ALLOW_IP_RANGE=0.0.0.0/0" | ||
| 58 | -docker run -d --name apache $set -p $port:80 $map -v $curPath/httpd.conf:/etc/httpd/conf/httpd.conf dci/apache:1.0 /usr/sbin/init | ||
| 59 | -docker exec -d apache systemctl start httpd | ||
| 60 | - |
请
注册
或
登录
后发表评论