lesscode-flask 0.0.79__tar.gz → 0.0.81__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/PKG-INFO +1 -1
  2. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/__init__.py +16 -8
  3. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/app.py +4 -1
  4. lesscode_flask-0.0.81/lesscode_flask/export_data/data_download_handler.py +94 -0
  5. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/setting/__init__.py +1 -1
  6. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/setup/__init__.py +38 -1
  7. lesscode_flask-0.0.81/lesscode_flask/utils/oss/__init__.py +0 -0
  8. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask.egg-info/PKG-INFO +1 -1
  9. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask.egg-info/SOURCES.txt +2 -0
  10. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/README.md +0 -0
  11. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/db/__init__.py +0 -0
  12. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/db/datasource.py +0 -0
  13. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/db/executor.py +0 -0
  14. {lesscode_flask-0.0.79/lesscode_flask/utils/decorator → lesscode_flask-0.0.81/lesscode_flask/export_data}/__init__.py +0 -0
  15. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/log/access_log_handler.py +0 -0
  16. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/model/access_log.py +0 -0
  17. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/model/auth_client.py +0 -0
  18. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/model/auth_permission.py +0 -0
  19. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/model/base_model.py +0 -0
  20. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/model/parameterized_query.py +0 -0
  21. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/model/response_result.py +0 -0
  22. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/model/user.py +0 -0
  23. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/service/access_log_service.py +0 -0
  24. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/service/auth_client_service.py +0 -0
  25. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/service/auth_permission_service.py +0 -0
  26. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/service/authentication_service.py +0 -0
  27. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/service/base_service.py +0 -0
  28. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/__init__.py +0 -0
  29. {lesscode_flask-0.0.79/lesscode_flask/utils/oss → lesscode_flask-0.0.81/lesscode_flask/utils/decorator}/__init__.py +0 -0
  30. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/decorator/cache.py +0 -0
  31. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/decorator/swagger.py +0 -0
  32. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/file/file_exporter.py +0 -0
  33. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/helpers.py +0 -0
  34. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/json/NotSortJSONProvider.py +0 -0
  35. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/oss/ks3_oss.py +0 -0
  36. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/redis/redis_helper.py +0 -0
  37. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/request/request.py +0 -0
  38. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/swagger/swagger_template.py +0 -0
  39. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/swagger/swagger_util.py +0 -0
  40. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/utils/thread/thread_utils.py +0 -0
  41. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask/wsgi.py +0 -0
  42. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask.egg-info/dependency_links.txt +0 -0
  43. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask.egg-info/requires.txt +0 -0
  44. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/lesscode_flask.egg-info/top_level.txt +0 -0
  45. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/query_runner/__init__.py +0 -0
  46. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/query_runner/clickhouse.py +0 -0
  47. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/query_runner/elasticsearch.py +0 -0
  48. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/query_runner/kingbase.py +0 -0
  49. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/query_runner/mysql.py +0 -0
  50. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/query_runner/pg.py +0 -0
  51. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/settings/__init__.py +0 -0
  52. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/settings/helpers.py +0 -0
  53. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/utils/__init__.py +0 -0
  54. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/redash/utils/requests_session.py +0 -0
  55. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/setup.cfg +0 -0
  56. {lesscode_flask-0.0.79 → lesscode_flask-0.0.81}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lesscode-flask
3
- Version: 0.0.79
3
+ Version: 0.0.81
4
4
  Summary: lesscode-flask 是基于flask的web开发脚手架项目,该项目初衷为简化开发过程,让研发人员更加关注业务。
5
5
  Home-page: https://lesscode-flask
6
6
  Author: Chao.yy
@@ -1,10 +1,12 @@
1
- __version__ = '0.0.79'
1
+ __version__ = '0.0.81'
2
2
 
3
3
  import functools
4
4
  import logging
5
5
  import traceback
6
6
 
7
7
  from flask import Blueprint
8
+
9
+ from lesscode_flask.export_data.data_download_handler import download_func_dict
8
10
  from lesscode_flask.utils.decorator.cache import deal_cache
9
11
 
10
12
 
@@ -15,11 +17,13 @@ class SQ_Blueprint(Blueprint):
15
17
  super().__init__(name=name, url_prefix=url_prefix, **kwargs)
16
18
 
17
19
  def decorator_handler(self, title: str, url: str = None, cache_enalbe: bool = False, cache_ex: int = 3600 * 10,
18
- content_type: str = "json", methods=['POST']):
20
+ content_type: str = "json", methods=['POST'], export_enable: bool = False):
19
21
  options = {"methods": methods}
20
22
 
21
23
  def decorator(func):
22
24
  path = url if url else "/{}".format(func.__name__)
25
+ download_key = func.__module__ + "." + func.__name__
26
+ download_func_dict[download_key] = func
23
27
 
24
28
  @functools.wraps(func)
25
29
  def wrapper(*args, **kwargs):
@@ -31,9 +35,13 @@ class SQ_Blueprint(Blueprint):
31
35
  except Exception as e:
32
36
  logging.error(traceback.format_exc())
33
37
  data = func(*args, **kwargs)
34
- return data
35
- # 如果没有开启缓存,或者缓存未命中,则执行原始函数
36
- data = func(*args, **kwargs)
38
+ else:
39
+ # 如果没有开启缓存,或者缓存未命中,则执行原始函数
40
+ data = func(*args, **kwargs)
41
+ if isinstance(data, dict) and export_enable:
42
+ data.update({
43
+ "download_key": download_key
44
+ })
37
45
  return data
38
46
 
39
47
  wrapper._title = title
@@ -45,11 +53,11 @@ class SQ_Blueprint(Blueprint):
45
53
  return decorator
46
54
 
47
55
  def post_route(self, title: str, url: str = None, cache_enalbe: bool = False, cache_ex: int = 3600 * 10,
48
- content_type: str = "json", methods=['POST']):
49
- decorator = self.decorator_handler(title, url, cache_enalbe, cache_ex, content_type, methods)
56
+ content_type: str = "json", methods=['POST'], export_enable: bool = False):
57
+ decorator = self.decorator_handler(title, url, cache_enalbe, cache_ex, content_type, methods, export_enable)
50
58
  return decorator
51
59
 
52
60
  def get_route(self, title: str, url: str = None, cache_enalbe: bool = False, cache_ex: int = 3600 * 10,
53
61
  content_type: str = "json", methods=['GET']):
54
62
  decorator = self.decorator_handler(title, url, cache_enalbe, cache_ex, content_type, methods)
55
- return decorator
63
+ return decorator
@@ -16,7 +16,7 @@ from werkzeug.middleware.proxy_fix import ProxyFix
16
16
 
17
17
  from lesscode_flask.model.response_result import ResponseResult
18
18
  from lesscode_flask.setup import setup_blueprint, setup_logging, setup_query_runner, setup_swagger, setup_sql_alchemy, \
19
- setup_redis, setup_login_manager, setup_resource_register
19
+ setup_redis, setup_login_manager, setup_resource_register, setup_data_download
20
20
  from lesscode_flask.utils.helpers import inject_args, generate_uuid, app_config
21
21
  from lesscode_flask.utils.json.NotSortJSONProvider import NotSortJSONProvider
22
22
  from lesscode_flask.utils.redis.redis_helper import RedisHelper
@@ -147,6 +147,9 @@ class Lesscoder(Flask):
147
147
  for blueprint_name, blueprint in blueprint_map.items():
148
148
  self.register_blueprint(blueprint)
149
149
  setup_resource_register(self)
150
+ setup_data_download(self)
151
+ # setup_static(self)
152
+
150
153
 
151
154
  @staticmethod
152
155
  def handle_exception(e):
@@ -0,0 +1,94 @@
1
+ import inspect
2
+ import logging
3
+ import os
4
+ from datetime import datetime
5
+
6
+ from flask import current_app
7
+ from openpyxl import Workbook
8
+ from openpyxl.styles import Alignment, Font
9
+
10
+ download_func_dict = {}
11
+
12
+
13
+ def upload_result_url(data_list: list, file_name: str = None, describe_text: str = None):
14
+ # 创建一个工作簿和一个工作表
15
+ wb = Workbook()
16
+ ws = wb.active
17
+ # 将数据写入工作表
18
+ for row in data_list:
19
+ row = [",".join(list(set(x))) if type(x) == list else str(x) for x in row]
20
+ ws.append(row)
21
+ # 自适应列宽
22
+ for index, col in enumerate(ws.columns):
23
+ max_length = max([len(str(data[index])) for data in data_list])
24
+ column = col[0].column_letter # 获取列字母
25
+ adjusted_width = min(60, (max_length * 2 + 2)) # 添加一些额外的空白以防止截断
26
+ ws.column_dimensions[column].width = adjusted_width
27
+ if describe_text:
28
+ ws.insert_rows(1, amount=1)
29
+ ws.merge_cells(f"A1:{column}1") # 合并第1行单元格
30
+ ws["A1"] = describe_text
31
+ # img = Image("./static/img/img.png")
32
+ # ws.add_image(img, "A1")
33
+ # 保存工作簿
34
+ file_key = f'{file_name}-{datetime.now().strftime("%Y%m%d%H%M%S")}.xlsx'
35
+ path = f'{current_app.config.get("STATIC_PATH", "")}/data_download/{file_key}'
36
+ wb.save(path)
37
+ clear_excel_task()
38
+ return f'{current_app.config.get("OUTSIDE_SCREEN_IP")}/static/data_download/{file_key}', file_key
39
+
40
+
41
+ def clear_excel_task():
42
+ delay = 3600 * 24
43
+ excel_path = os.path.join(current_app.config.get("STATIC_PATH", ""), "data_download")
44
+ files = get_files(excel_path)
45
+ for f in files:
46
+ now = datetime.now().timestamp()
47
+ if os.path.exists(f):
48
+ file_time = os.path.getctime(f)
49
+ if now - file_time > delay:
50
+ os.remove(f)
51
+ logging.info(f'delete file({f}) success')
52
+
53
+
54
+ def get_files(path):
55
+ files = []
56
+ fs = os.listdir(path)
57
+ for f in fs:
58
+ file_path = f'{path}/{f}'
59
+ if os.path.isfile(file_path):
60
+ if ".gitkeep" not in file_path:
61
+ files.append(file_path)
62
+ else:
63
+ ft = get_files(file_path)
64
+ files.extend(ft)
65
+ return files
66
+
67
+
68
+ def format_to_table_download(table_head_list=None, table_body_list=None):
69
+ if not table_head_list:
70
+ table_head_list = table_body_list["columns"]
71
+ table_body_list = table_body_list["dataSource"]
72
+ data_index_list = [one['dataIndex'] for one in table_head_list]
73
+ title_list = [one['title'] for one in table_head_list]
74
+ all_data_list = [title_list]
75
+ for one in table_body_list:
76
+ all_data_list.append([one.get(dataIndex, "") for dataIndex in data_index_list])
77
+ # table_head_map_dict = {one['dataIndex']: one['title'] for one in table_head_list}
78
+ #
79
+ # sta_map_dict = {}
80
+ # for one in table_body_list:
81
+ # for tag in data_index_list:
82
+ # if tag not in sta_map_dict:
83
+ # sta_map_dict[tag] = [one.get(tag, "")]
84
+ # else:
85
+ # sta_map_dict[tag].append(one.get(tag, ""))
86
+ # sta_map_dict = {table_head_map_dict[k]: v for k, v in sta_map_dict.items()}
87
+ return all_data_list
88
+
89
+
90
+ def convert_page(offset: int = None, size: int = None, page_num: int = None, page_size: int = None):
91
+ if not offset and not size:
92
+ offset = (page_num - 1) * page_size
93
+ size = page_size
94
+ return offset, size
@@ -61,7 +61,7 @@ class BaseConfig:
61
61
  # 应用运行根路径
62
62
  # APPLICATION_PATH: str = f"{os.path.abspath(os.path.dirname(sys.argv[0]))}"
63
63
  # # 静态资源目录
64
- STATIC_PATH: str = f"{os.path.abspath(os.path.dirname(sys.argv[0]))}"
64
+ STATIC_PATH: str = os.path.join(f"{os.path.abspath(os.path.dirname(sys.argv[0]))}", "static")
65
65
 
66
66
  SECRET_KEY = "423ad5ef841bbd073b415e4ba4136d7c94cac3f5e9bfeec1a21da35cd9ea6b46"
67
67
 
@@ -4,9 +4,11 @@ from datetime import datetime
4
4
  from importlib import import_module
5
5
  from logging.handlers import TimedRotatingFileHandler
6
6
 
7
- from flask import current_app
7
+ from flask import current_app, send_from_directory
8
8
 
9
+ from lesscode_flask import download_func_dict
9
10
  from lesscode_flask.db import db
11
+ from lesscode_flask.export_data.data_download_handler import convert_page, format_to_table_download, upload_result_url
10
12
  from lesscode_flask.log.access_log_handler import AccessLogHandler
11
13
  from lesscode_flask.model.user import AnonymousUser
12
14
  from lesscode_flask.service.authentication_service import get_token_user, get_api_user, get_gateway_user
@@ -400,3 +402,38 @@ def setup_resource_register(app):
400
402
  return res
401
403
  except Exception as e:
402
404
  raise e
405
+
406
+
407
+ # def setup_static(app):
408
+ # @app.route("/static/<filename>")
409
+ # def static_resource(filename, **kwargs):
410
+ # """
411
+ # 方法说明
412
+ # :param download_key:
413
+ # :return:
414
+ # """
415
+ # return send_from_directory('static', filename)
416
+
417
+
418
+ def setup_data_download(app):
419
+ @app.route(f"{current_app.config.get('ROUTE_PREFIX')}/download/data_download", methods=['POST'])
420
+ def data_download(download_key, params, column_list=None, page_size=10, file_name="", page_number=1, offset=0,
421
+ size=10):
422
+ """
423
+ 方法说明
424
+ :param download_key:
425
+ :return:
426
+ """
427
+ if not file_name:
428
+ file_name = "data_export"
429
+ func = download_func_dict.get(download_key, {})
430
+ offset, size = convert_page(offset, size, page_number, page_size)
431
+ request_param = {"offset": offset, "size": size}
432
+ signature = inspect.signature(func)
433
+ for parameter_name, parameter in signature.parameters.items():
434
+ if params.get(parameter_name):
435
+ request_param[parameter_name] = params[parameter_name]
436
+ table_body_list = func(**request_param)
437
+ sta_map_dict = format_to_table_download(table_head_list=column_list, table_body_list=table_body_list)
438
+ url, file_key = upload_result_url(sta_map_dict, file_name=file_name)
439
+ return url
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lesscode-flask
3
- Version: 0.0.79
3
+ Version: 0.0.81
4
4
  Summary: lesscode-flask 是基于flask的web开发脚手架项目,该项目初衷为简化开发过程,让研发人员更加关注业务。
5
5
  Home-page: https://lesscode-flask
6
6
  Author: Chao.yy
@@ -11,6 +11,8 @@ lesscode_flask.egg-info/top_level.txt
11
11
  lesscode_flask/db/__init__.py
12
12
  lesscode_flask/db/datasource.py
13
13
  lesscode_flask/db/executor.py
14
+ lesscode_flask/export_data/__init__.py
15
+ lesscode_flask/export_data/data_download_handler.py
14
16
  lesscode_flask/log/access_log_handler.py
15
17
  lesscode_flask/model/access_log.py
16
18
  lesscode_flask/model/auth_client.py