正在显示
17 个修改的文件
包含
1390 行增加
和
220 行删除
... | ... | @@ -8,15 +8,17 @@ from app.models import Database,db,DES,Table,Columns,TableVacuate |
8 | 8 | import uuid |
9 | 9 | from . import database_test |
10 | 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 | 12 | from sqlalchemy.orm import Session |
13 | 13 | from sqlalchemy import create_engine |
14 | 14 | from sqlalchemy.orm import sessionmaker |
15 | 15 | from app.util.component.ApiTemplate import ApiTemplate |
16 | 16 | from app.util.component.PGUtil import PGUtil |
17 | +from app.util.component.SQLUtil import SQLUtil | |
17 | 18 | from app.util.component.GeometryAdapter import GeometryAdapter |
19 | +from app.util.component.StructuredPrint import StructurePrint | |
18 | 20 | class Api(ApiTemplate): |
19 | - api_name = "数据库注册" | |
21 | + api_name = "注册数据库" | |
20 | 22 | def process(self): |
21 | 23 | res ={} |
22 | 24 | res["result"] = False |
... | ... | @@ -29,7 +31,7 @@ class Api(ApiTemplate): |
29 | 31 | encryption = int(self.para.get("encryption","0")) |
30 | 32 | if encryption: |
31 | 33 | passwd = DES.decode(passwd) |
32 | - | |
34 | + | |
33 | 35 | sqlalchemy_uri = "postgresql://{}:{}@{}:{}/{}".format(user,passwd,host,port,database) |
34 | 36 | connectsrt = "hostaddr={} port={} dbname='{}' user='{}' password='{}'".format(host,port,database,user,passwd) |
35 | 37 | |
... | ... | @@ -87,26 +89,29 @@ class Api(ApiTemplate): |
87 | 89 | |
88 | 90 | def register_table(self,database): |
89 | 91 | this_time = datetime.datetime.now() |
92 | + | |
90 | 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 | 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 | 109 | spatial_table_name =[] |
106 | 110 | tables=[] |
107 | 111 | for i in range(pg_ds.GetLayerCount()): |
108 | 112 | layer: Layer = pg_ds.GetLayer(i) |
109 | 113 | l_name = layer.GetName() |
114 | + | |
110 | 115 | # 只注册public的空间表,其他表空间的表名会有. |
111 | 116 | if layer.GetName().__contains__("."): |
112 | 117 | continue |
... | ... | @@ -116,9 +121,15 @@ class Api(ApiTemplate): |
116 | 121 | spatial_table_name.append(layer.GetName()) |
117 | 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 | 129 | # 范围统计和数量统计以100w为界限 |
120 | 130 | query_count_layer: Layer = pg_ds.ExecuteSQL( |
121 | 131 | '''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format(l_name)) |
132 | + | |
122 | 133 | feature_count = query_count_layer.GetFeature(0).GetField("ec") |
123 | 134 | # 要素少于100w可以精确统计 |
124 | 135 | if feature_count < 1000000: |
... | ... | @@ -137,11 +148,13 @@ class Api(ApiTemplate): |
137 | 148 | |
138 | 149 | table_guid = uuid.uuid1().__str__() |
139 | 150 | |
151 | + geom_type = GeometryAdapter.get_geometry_type(layer) | |
152 | + | |
140 | 153 | table = Table(guid=table_guid, |
141 | 154 | database_guid=database.guid, |
142 | 155 | # alias=layer.GetName(), |
143 | 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 | 158 | extent=extent, |
146 | 159 | feature_count=feature_count |
147 | 160 | ) |
... | ... | @@ -164,19 +177,26 @@ class Api(ApiTemplate): |
164 | 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 | 182 | db_session: Session = PGUtil.get_db_session(DES.decode(database.sqlalchemy_uri)) |
170 | 183 | |
171 | 184 | # 只注册public中的表 |
172 | 185 | result = db_session.execute( |
173 | 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 | 188 | for re in result: |
175 | 189 | table_name = re[0] |
176 | 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 | 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 | 201 | table = Table(guid=table_guid, |
182 | 202 | database_guid=database.guid, |
... | ... | @@ -209,15 +229,26 @@ class Api(ApiTemplate): |
209 | 229 | column = Columns(guid=uuid.uuid1().__str__(), table_guid=table_guid, |
210 | 230 | name=col[1], create_time=this_time, update_time=this_time) |
211 | 231 | db.session.add(column) |
232 | + db_session.commit() | |
212 | 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 | 239 | for i in range(pg_ds.GetLayerCount()): |
218 | 240 | layer:Layer = pg_ds.GetLayer(i) |
219 | 241 | l_name = layer.GetName() |
242 | + | |
243 | + | |
244 | + | |
220 | 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 | 252 | base_layer_name=l_name.split("_vacuate_")[0] |
222 | 253 | level = l_name.split("_")[-2] |
223 | 254 | pixel_distance_str: str ="0" |
... | ... | @@ -227,15 +258,17 @@ class Api(ApiTemplate): |
227 | 258 | pixel_distance_str="0.{}".format(pixel_distance_str) |
228 | 259 | except: |
229 | 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 | 280 | engine = create_engine(sqlachemy_uri) |
248 | 281 | system_session = sessionmaker(bind=engine)() |
249 | 282 | system_session.execute(test_sql).fetchone() |
250 | - | |
251 | 283 | except: |
252 | 284 | check = False |
253 | 285 | finally: |
... | ... | @@ -281,10 +313,6 @@ class Api(ApiTemplate): |
281 | 313 | {"name": "alias", |
282 | 314 | "in": "formData", |
283 | 315 | "type": "string","description":"数据库别名","required": "true"}, |
284 | - | |
285 | - {"name": "encryption", | |
286 | - "in": "formData", | |
287 | - "type": "integer", "description": "密码是否加密", "enum": [0,1]}, | |
288 | 316 | ], |
289 | 317 | "responses":{ |
290 | 318 | 200:{ | ... | ... |
... | ... | @@ -8,28 +8,28 @@ from app.models import * |
8 | 8 | |
9 | 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 | 13 | import os |
14 | 14 | import uuid |
15 | 15 | import configure |
16 | 16 | from app.util.component.ApiTemplate import ApiTemplate |
17 | 17 | from app.util.component.PGUtil import PGUtil |
18 | 18 | from app.util.component.ZipUtil import ZipUtil |
19 | + | |
19 | 20 | class Api(ApiTemplate): |
20 | 21 | |
21 | - api_name = "下载数据" | |
22 | 22 | def process(self): |
23 | 23 | #获取参数 |
24 | 24 | |
25 | 25 | #返回结果 |
26 | - res={} | |
26 | + result={} | |
27 | 27 | #设置编码 |
28 | 28 | encoding = self.para.get("encoding") |
29 | 29 | if encoding: |
30 | 30 | gdal.SetConfigOption("SHAPE_ENCODING",encoding) |
31 | 31 | else: |
32 | - gdal.SetConfigOption("SHAPE_ENCODING", "GBK") | |
32 | + gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8") | |
33 | 33 | |
34 | 34 | ds:DataSource = None |
35 | 35 | try: |
... | ... | @@ -38,6 +38,7 @@ class Api(ApiTemplate): |
38 | 38 | database = Database.query.filter_by(guid=database_guid).one_or_none() |
39 | 39 | if not database: |
40 | 40 | raise Exception("数据库不存在!") |
41 | + | |
41 | 42 | |
42 | 43 | ds:DataSource = PGUtil.open_pg_data_source(0,DES.decode(database.sqlalchemy_uri)) |
43 | 44 | |
... | ... | @@ -49,16 +50,16 @@ class Api(ApiTemplate): |
49 | 50 | if download_type.__eq__("gdb"): |
50 | 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 | 55 | except Exception as e: |
55 | 56 | print(traceback.format_exc()) |
56 | - res["msg"]= e.__str__() | |
57 | - res["result"]=False | |
57 | + result["message"]= e.__str__() | |
58 | + result["state"]=-1 | |
58 | 59 | finally: |
59 | 60 | if ds: |
60 | 61 | ds.Destroy() |
61 | - return res | |
62 | + return result | |
62 | 63 | |
63 | 64 | |
64 | 65 | def download_shp(self,table_names,ds): |
... | ... | @@ -77,9 +78,23 @@ class Api(ApiTemplate): |
77 | 78 | dirpath = os.path.join(parent, "file_tmp", uuid_) |
78 | 79 | os.makedirs(dirpath) |
79 | 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 | 93 | data_source.Destroy() |
94 | + | |
95 | + | |
82 | 96 | ZipUtil.create_zip(os.path.join(parent, "file_tmp", table_name+"_"+uuid_) + ".zip", [dirpath]) |
97 | + | |
83 | 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 | 129 | # if not table_alias: |
115 | 130 | # table_alias = table_name |
116 | 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 | 154 | gdb_ds.Destroy() |
121 | 155 | ZipUtil.create_zip(gdb_path + ".zip", [gdb_path]) |
122 | 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 | 159 | return data |
126 | 160 | ... | ... |
... | ... | @@ -18,6 +18,10 @@ from . import table_refresh |
18 | 18 | from . import table_delete |
19 | 19 | from . import table_view |
20 | 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 | 25 | class DataManager(BlueprintApi): |
22 | 26 | |
23 | 27 | bp = Blueprint("DataManager", __name__, url_prefix="/API/Manager") |
... | ... | @@ -106,4 +110,41 @@ class DataManager(BlueprintApi): |
106 | 110 | """ |
107 | 111 | 数据抽稀 |
108 | 112 | """ |
109 | - return table_vacuate.Api().result | |
\ No newline at end of file | ||
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 | |
\ No newline at end of file | ... | ... |
... | ... | @@ -40,6 +40,10 @@ class Api(ApiTemplate): |
40 | 40 | tables = Table.query.order_by(Table.update_time.desc(),Table.name) |
41 | 41 | else: |
42 | 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 | 47 | if database_guid: |
44 | 48 | tables = tables.filter_by(database_guid=database_guid) |
45 | 49 | if catalog_guid: | ... | ... |
... | ... | @@ -13,7 +13,7 @@ import datetime |
13 | 13 | import uuid |
14 | 14 | |
15 | 15 | from sqlalchemy.orm import Session |
16 | - | |
16 | +from app.util.component.SQLUtil import SQLUtil | |
17 | 17 | from app.util.component.PGUtil import PGUtil |
18 | 18 | from app.util.component.ModelVisitor import ModelVisitor |
19 | 19 | from app.util.component.StructuredPrint import StructurePrint |
... | ... | @@ -70,6 +70,8 @@ class Api(ApiTemplate): |
70 | 70 | data_session=None |
71 | 71 | result = {} |
72 | 72 | sys_session = None |
73 | + db_tuple = PGUtil.get_info_from_sqlachemy_uri(DES.decode(database.sqlalchemy_uri)) | |
74 | + | |
73 | 75 | try: |
74 | 76 | sys_session = PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI) |
75 | 77 | |
... | ... | @@ -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 | 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 | 106 | sys_session.commit() |
... | ... | @@ -133,11 +135,11 @@ class Api(ApiTemplate): |
133 | 135 | # 增加新普通表 |
134 | 136 | |
135 | 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 | 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 | 144 | sys_session.commit() |
143 | 145 | result["data"] = "刷新数据成功!" |
... | ... | @@ -168,7 +170,7 @@ class Api(ApiTemplate): |
168 | 170 | sys_session.close() |
169 | 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 | 176 | :param database: |
... | ... | @@ -196,10 +198,17 @@ class Api(ApiTemplate): |
196 | 198 | if layer.GetName().__contains__("_vacuate_"): |
197 | 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 | 207 | # 范围统计和数量统计以100w为界限 |
200 | 208 | query_count_layer: Layer = pg_ds.ExecuteSQL( |
201 | 209 | '''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format( |
202 | 210 | l_name)) |
211 | + | |
203 | 212 | feature_count = query_count_layer.GetFeature(0).GetField("ec") |
204 | 213 | # 要素少于100w可以精确统计 |
205 | 214 | if feature_count < 1000000: |
... | ... | @@ -218,12 +227,14 @@ class Api(ApiTemplate): |
218 | 227 | |
219 | 228 | StructurePrint.print("空间表增加!") |
220 | 229 | |
230 | + geom_type = GeometryAdapter.get_geometry_type(layer) | |
231 | + | |
221 | 232 | table_guid = uuid.uuid1().__str__() |
222 | 233 | table = Table(guid=table_guid, |
223 | 234 | database_guid=database.guid, |
224 | 235 | # alias=layer.GetName(), |
225 | 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 | 238 | extent=extent, |
228 | 239 | feature_count=feature_count |
229 | 240 | ) |
... | ... | @@ -240,7 +251,7 @@ class Api(ApiTemplate): |
240 | 251 | sys_session.add(column) |
241 | 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 | 257 | for i in range(pg_ds.GetLayerCount()): |
... | ... | @@ -255,6 +266,10 @@ class Api(ApiTemplate): |
255 | 266 | if layer.GetName().__contains__("_vacuate_"): |
256 | 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 | 274 | base_layer_name = l_name.split("_vacuate_")[0] |
260 | 275 | level = l_name.split("_")[-2] |
... | ... | @@ -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 | 305 | for table in spatial_tables: |
289 | 306 | |
... | ... | @@ -303,6 +320,12 @@ class Api(ApiTemplate): |
303 | 320 | if layer.GetName().__contains__("_vacuate_"): |
304 | 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 | 329 | columns = table.relate_columns |
307 | 330 | columns_names = [column.name for column in columns] |
308 | 331 | feature_defn: FeatureDefn = layer.GetLayerDefn() |
... | ... | @@ -357,11 +380,18 @@ class Api(ApiTemplate): |
357 | 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 | 384 | for table_name in real_common_tables_name: |
362 | 385 | if table_name not in origin_common_tables_name: |
363 | 386 | StructurePrint.print("{}非空间表增加!".format(table_name)) |
364 | 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 | 395 | count = data_session.execute('select count(*) from "{}"'.format(table_name)).fetchone()[0] |
366 | 396 | |
367 | 397 | table = Table(guid=table_guid, |
... | ... | @@ -402,7 +432,7 @@ class Api(ApiTemplate): |
402 | 432 | for table in tables: |
403 | 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 | 436 | for table_name in origin_common_tables_name: |
407 | 437 | tables = sys_session.query(Table).filter_by(name=table_name).filter_by(database_guid=database_guid).all() |
408 | 438 | for table in tables: |
... | ... | @@ -411,6 +441,13 @@ class Api(ApiTemplate): |
411 | 441 | sys_session.delete(table) |
412 | 442 | # 修改表 |
413 | 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 | 451 | columns = table.relate_columns |
415 | 452 | columns_names = [column.name for column in columns] |
416 | 453 | |
... | ... | @@ -448,15 +485,15 @@ class Api(ApiTemplate): |
448 | 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 | 493 | if not table.feature_count.__eq__(count): |
455 | 494 | StructurePrint.print("{}表要素变化!".format(table_name)) |
456 | 495 | sys_session.query(Table).filter_by(guid=table.guid).update({"feature_count": count}) |
457 | 496 | |
458 | - | |
459 | - | |
460 | 497 | |
461 | 498 | api_doc={ |
462 | 499 | "tags":["管理接口"], | ... | ... |
... | ... | @@ -5,19 +5,23 @@ |
5 | 5 | |
6 | 6 | import datetime |
7 | 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 | 10 | from sqlalchemy.engine import ResultProxy |
11 | 11 | from app.util.component.ApiTemplate import ApiTemplate |
12 | 12 | from app.util.component.PGUtil import PGUtil |
13 | 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 | 16 | import multiprocessing |
15 | 17 | import uuid |
16 | 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 | 25 | def process(self): |
22 | 26 | |
23 | 27 | res = {} |
... | ... | @@ -26,15 +30,21 @@ class Api(ApiTemplate): |
26 | 30 | try: |
27 | 31 | table_guid = self.para.get("guid") |
28 | 32 | table: Table = Table.query.filter_by(guid=table_guid).one_or_none() |
33 | + | |
29 | 34 | if not table: |
30 | 35 | raise Exception("数据不存在!") |
31 | 36 | |
32 | - # 判断图层是否存在 | |
33 | - | |
34 | 37 | pg_ds :DataSource= PGUtil.open_pg_data_source(0,DES.decode(table.relate_database.sqlalchemy_uri)) |
35 | 38 | layer = pg_ds.GetLayerByName(table.name) |
39 | + # 判断图层是否存在 | |
36 | 40 | if not layer: |
37 | 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 | 48 | if pg_ds: |
39 | 49 | pg_ds.Destroy() |
40 | 50 | |
... | ... | @@ -46,17 +56,22 @@ class Api(ApiTemplate): |
46 | 56 | res["result"] = False |
47 | 57 | res["msg"] = "非空间表!" |
48 | 58 | return res |
59 | + | |
49 | 60 | # if table.is_vacuate==1: |
50 | 61 | # res["state"] = -1 |
51 | 62 | # res["message"] = "已精化!" |
52 | 63 | # return res |
53 | 64 | |
54 | 65 | |
66 | + | |
55 | 67 | # 初始化task |
56 | 68 | task_guid = uuid.uuid1().__str__() |
57 | 69 | vacuate_process = multiprocessing.Process(target=self.task,args=(table,task_guid)) |
58 | 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 | 76 | task = Task(guid=task_guid, |
62 | 77 | name="{}精化".format(table.name), |
... | ... | @@ -67,12 +82,15 @@ class Api(ApiTemplate): |
67 | 82 | creator=self.para.get("creator"), |
68 | 83 | file_name=None, |
69 | 84 | database_guid=table.database_guid, |
70 | - process="精化中") | |
85 | + process="精化中", | |
86 | + parameter=",".join([str(x) for x in ref_grids])) | |
87 | + | |
71 | 88 | db.session.add(task) |
72 | 89 | db.session.commit() |
73 | 90 | res["msg"] = "图层抽稀已提交!" |
74 | - res["data"] = table_guid | |
91 | + res["data"] = task_guid | |
75 | 92 | res["result"] = True |
93 | + | |
76 | 94 | except Exception as e: |
77 | 95 | raise e |
78 | 96 | finally: |
... | ... | @@ -87,23 +105,34 @@ class Api(ApiTemplate): |
87 | 105 | pg_ds = None |
88 | 106 | vacuate_process = None |
89 | 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 | 109 | sys_session.query(Table).filter_by(guid=table.guid).update( |
94 | 110 | {"is_vacuate": 2, "update_time": datetime.datetime.now()}) |
95 | 111 | sys_session.commit() |
96 | 112 | |
113 | + | |
97 | 114 | database = sys_session.query(Database).filter_by(guid=table.database_guid).one_or_none() |
98 | 115 | pg_session = PGUtil.get_db_session(DES.decode(database.sqlalchemy_uri)) |
99 | 116 | |
100 | 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 | 130 | options = ["OVERWRITE=yes", "GEOMETRY_NAME={}".format(PGUtil.get_geo_column(table.name,pg_session)), |
104 | 131 | "PRECISION=NO"] |
132 | + | |
105 | 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 | 138 | for feature in layer: |
... | ... | @@ -112,14 +141,28 @@ class Api(ApiTemplate): |
112 | 141 | if geo is not None: |
113 | 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 | 158 | sys_session.query(Table).filter_by(guid=table.guid).update( |
117 | 159 | {"is_vacuate": 1, "update_time": datetime.datetime.now()}) |
118 | 160 | sys_session.commit() |
119 | 161 | |
120 | 162 | except Exception as e: |
121 | 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 | 166 | sys_session.query(Table).filter_by(guid=table.guid).update( |
124 | 167 | {"is_vacuate": 0, "update_time": datetime.datetime.now()}) |
125 | 168 | |
... | ... | @@ -129,7 +172,8 @@ class Api(ApiTemplate): |
129 | 172 | task_guid=task_guid) |
130 | 173 | sys_session.add(task_process) |
131 | 174 | sys_session.commit() |
132 | - vacuate_process.rollback() | |
175 | + if vacuate_process: | |
176 | + vacuate_process.rollback() | |
133 | 177 | |
134 | 178 | print(traceback.format_exc()) |
135 | 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 | + } | |
\ No newline at end of file | ... | ... |
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() | |
\ No newline at end of file | ... | ... |
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 | 16 | import traceback |
17 | 17 | import copy |
18 | 18 | from app.util.component.GeometryAdapter import GeometryAdapter |
19 | +from app.util.component.VacuateConf import VacuateConf | |
19 | 20 | class EntryDataVacuate: |
20 | 21 | |
21 | 22 | def entry(self,parameter): |
... | ... | @@ -317,13 +318,15 @@ class ThisTask: |
317 | 318 | else: |
318 | 319 | ext = [round(e, 2) for e in ext] |
319 | 320 | |
321 | + geom_type = GeometryAdapter.get_geometry_type(layer) | |
322 | + | |
320 | 323 | extent = "{},{},{},{}".format(ext[0], ext[1], ext[2], ext[3]) |
321 | 324 | table_guid = uuid.uuid1().__str__() |
322 | 325 | table = Table(guid=table_guid, |
323 | 326 | database_guid=self.database.guid, |
324 | 327 | creator=creator, |
325 | 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 | 330 | extent=extent, |
328 | 331 | feature_count=layer.GetFeatureCount(), |
329 | 332 | is_vacuate=is_vacuate |
... | ... | @@ -353,13 +356,16 @@ class ThisTask: |
353 | 356 | # 抽稀表有固定的命名规则 |
354 | 357 | for level,layer in vacuate_layers.items(): |
355 | 358 | pixel_distance_str:str=layer.GetName().split("_")[-1] |
359 | + lev = layer.GetName().split("_")[-2] | |
360 | + | |
356 | 361 | if pixel_distance_str.startswith("0"): |
357 | 362 | pixel_distance_str="0.{}".format(pixel_distance_str) |
358 | 363 | |
359 | 364 | pixel_distance = float(pixel_distance_str) |
365 | + | |
360 | 366 | table_vacuate = TableVacuate(guid=uuid.uuid1().__str__(), |
361 | 367 | table_guid=table_guid, |
362 | - level=level, | |
368 | + level=int(lev), | |
363 | 369 | name=layer.GetName(), |
364 | 370 | pixel_distance=pixel_distance) |
365 | 371 | self.sys_session.add(table_vacuate) |
... | ... | @@ -398,14 +404,18 @@ class VacuateProcess: |
398 | 404 | vacuate_layers_gridsize={} |
399 | 405 | pg_ds_dict = {} |
400 | 406 | # 图层要素大于5W才抽稀 |
401 | - least_vacuate_count = 20000 | |
407 | + least_vacuate_count = VacuateConf.least_vacuate_count | |
402 | 408 | |
403 | 409 | extent=[] |
404 | 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 | 419 | this_gridsize=[] |
410 | 420 | |
411 | 421 | |
... | ... | @@ -453,17 +463,17 @@ class VacuateProcess: |
453 | 463 | ###### |
454 | 464 | |
455 | 465 | if extent[0]>180: |
456 | - t_grid_size=self.project_gridsize | |
466 | + self.t_grid_size=self.project_gridsize | |
457 | 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 | 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 | 477 | print(grid_size) |
468 | 478 | self.this_gridsize.append(grid_size) |
469 | 479 | self.max_level += 1 |
... | ... | @@ -479,6 +489,7 @@ class VacuateProcess: |
479 | 489 | # 生成抽稀图层 |
480 | 490 | options = options[1:] |
481 | 491 | options.append("OVERWRITE=yes") |
492 | + options.append("LAUNDER=no") | |
482 | 493 | for l in range(self.max_level): |
483 | 494 | this_grid_len = self.this_gridsize[l] |
484 | 495 | |
... | ... | @@ -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 | 512 | ogr.wkbUnknown, options) |
501 | 513 | # 抽稀表不需要属性 |
502 | 514 | # vl.CreateFields(schema) | ... | ... |
... | ... | @@ -5,8 +5,6 @@ |
5 | 5 | from osgeo import ogr |
6 | 6 | from sqlalchemy import create_engine |
7 | 7 | from sqlalchemy.orm import sessionmaker,Session |
8 | -from sqlalchemy.engine import ResultProxy | |
9 | - | |
10 | 8 | class PGUtil: |
11 | 9 | |
12 | 10 | @classmethod |
... | ... | @@ -27,11 +25,6 @@ class PGUtil: |
27 | 25 | |
28 | 26 | @classmethod |
29 | 27 | def get_info_from_sqlachemy_uri(cls,uri): |
30 | - ''' | |
31 | - 解析sqlachemy_uri | |
32 | - :param uri: | |
33 | - :return: | |
34 | - ''' | |
35 | 28 | parts = uri.split(":") |
36 | 29 | user = parts[1][2:] |
37 | 30 | |
... | ... | @@ -56,12 +49,7 @@ class PGUtil: |
56 | 49 | |
57 | 50 | @classmethod |
58 | 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 | 53 | geom_col_sql = ''' |
66 | 54 | SELECT a.attname AS field,t.typname AS type |
67 | 55 | FROM |
... | ... | @@ -75,7 +63,7 @@ class PGUtil: |
75 | 63 | and a.atttypid = t.oid |
76 | 64 | '''.format(table_name) |
77 | 65 | geom_col = None |
78 | - geom_result: ResultProxy = db_session.execute(geom_col_sql) | |
66 | + geom_result = db_session.execute(geom_col_sql) | |
79 | 67 | for row_proxy in geom_result: |
80 | 68 | if row_proxy[1].__eq__("geometry"): |
81 | 69 | geom_col = row_proxy[0] |
... | ... | @@ -84,39 +72,39 @@ class PGUtil: |
84 | 72 | |
85 | 73 | @classmethod |
86 | 74 | def get_table_count(cls,table_name,db_session): |
87 | - ''' | |
88 | - 获取图层数量 | |
89 | - :param table_name: | |
90 | - :param db_session: | |
91 | - :return: | |
92 | - ''' | |
93 | 75 | count_result = db_session.execute('''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format( |
94 | 76 | table_name)).fetchone() |
95 | 77 | count = count_result[0] |
96 | 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 | 80 | count=count_result[0] |
99 | 81 | return count |
100 | 82 | |
101 | 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 | 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 | |
\ No newline at end of file | ... | ... |
... | ... | @@ -8,11 +8,45 @@ class SQLUtil: |
8 | 8 | |
9 | 9 | |
10 | 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 | 18 | return count |
14 | 19 | |
15 | 20 | @classmethod |
16 | 21 | def rename(cls,session,origin,after_name): |
17 | 22 | rename_sql = 'alter table "{}" rename to "{}"'.format(origin, after_name) |
18 | 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 | |
\ No newline at end of file | ... | ... |
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] | |
\ No newline at end of file | ... | ... |
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> | |
\ No newline at end of file | ||
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 | - |
请
注册
或
登录
后发表评论