fastgenerateapi 0.0.28__py2.py3-none-any.whl → 1.1.7__py2.py3-none-any.whl

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.

Potentially problematic release.


This version of fastgenerateapi might be problematic. Click here for more details.

Files changed (80) hide show
  1. fastgenerateapi/__init__.py +2 -2
  2. fastgenerateapi/__version__.py +1 -1
  3. fastgenerateapi/api_view/base_view.py +17 -7
  4. fastgenerateapi/api_view/create_view.py +1 -1
  5. fastgenerateapi/api_view/delete_filter_view.py +1 -1
  6. fastgenerateapi/api_view/delete_tree_view.py +3 -3
  7. fastgenerateapi/api_view/delete_view.py +3 -3
  8. fastgenerateapi/api_view/get_all_view.py +10 -8
  9. fastgenerateapi/api_view/get_one_view.py +1 -1
  10. fastgenerateapi/api_view/get_relation_view.py +1 -1
  11. fastgenerateapi/api_view/get_tree_view.py +1 -1
  12. fastgenerateapi/api_view/mixin/base_mixin.py +11 -7
  13. fastgenerateapi/api_view/mixin/dbmodel_mixin.py +30 -20
  14. fastgenerateapi/api_view/mixin/response_mixin.py +68 -38
  15. fastgenerateapi/api_view/mixin/tool_mixin.py +1 -357
  16. fastgenerateapi/api_view/mixin/utils/__init__.py +0 -0
  17. fastgenerateapi/api_view/mixin/utils/docx_util.py +399 -0
  18. fastgenerateapi/api_view/mixin/utils/file_util.py +30 -0
  19. fastgenerateapi/api_view/mixin/utils/pdf_util.py +76 -0
  20. fastgenerateapi/api_view/mixin/utils/xlsx_util.py +336 -0
  21. fastgenerateapi/api_view/mixin/utils/zip_util.py +50 -0
  22. fastgenerateapi/api_view/switch_view.py +2 -2
  23. fastgenerateapi/api_view/update_relation_view.py +3 -3
  24. fastgenerateapi/api_view/update_view.py +1 -1
  25. fastgenerateapi/cache/cache_decorator.py +1 -1
  26. fastgenerateapi/controller/filter_controller.py +68 -26
  27. fastgenerateapi/controller/router_controller.py +9 -9
  28. fastgenerateapi/controller/rpc_controller.py +1 -1
  29. fastgenerateapi/controller/ws_controller.py +1 -1
  30. fastgenerateapi/deps/filter_params_deps.py +34 -4
  31. fastgenerateapi/deps/paginator_deps.py +4 -4
  32. fastgenerateapi/deps/tree_params_deps.py +4 -4
  33. fastgenerateapi/fastapi_utils/__init__.py +0 -0
  34. fastgenerateapi/fastapi_utils/all.py +5 -0
  35. fastgenerateapi/fastapi_utils/param_utils.py +37 -0
  36. fastgenerateapi/fastapi_utils/response_utils.py +344 -0
  37. fastgenerateapi/model/__init__.py +0 -0
  38. fastgenerateapi/model/base_model.py +56 -0
  39. fastgenerateapi/my_fields/enum_field.py +5 -5
  40. fastgenerateapi/my_fields/validator.py +60 -0
  41. fastgenerateapi/pydantic_utils/base_model.py +46 -20
  42. fastgenerateapi/pydantic_utils/base_settings.py +16 -0
  43. fastgenerateapi/pydantic_utils/json_encoders.py +2 -1
  44. fastgenerateapi/schemas_factory/common_function.py +1 -1
  45. fastgenerateapi/schemas_factory/common_schema_factory.py +4 -4
  46. fastgenerateapi/schemas_factory/create_schema_factory.py +4 -4
  47. fastgenerateapi/schemas_factory/filter_schema_factory.py +6 -6
  48. fastgenerateapi/schemas_factory/get_all_schema_factory.py +5 -5
  49. fastgenerateapi/schemas_factory/get_one_schema_factory.py +4 -3
  50. fastgenerateapi/schemas_factory/get_relation_schema_factory.py +3 -3
  51. fastgenerateapi/schemas_factory/get_tree_schema_factory.py +3 -3
  52. fastgenerateapi/schemas_factory/response_factory.py +3 -3
  53. fastgenerateapi/schemas_factory/sql_get_all_schema_factory.py +3 -3
  54. fastgenerateapi/schemas_factory/update_schema_factory.py +4 -4
  55. fastgenerateapi/settings/__init__.py +6 -0
  56. fastgenerateapi/settings/all_settings.py +91 -0
  57. fastgenerateapi/settings/{settings.py → app_settings.py} +9 -9
  58. fastgenerateapi/settings/db_settings.py +69 -0
  59. fastgenerateapi/settings/file_settings.py +24 -0
  60. fastgenerateapi/settings/jwt_settings.py +23 -0
  61. fastgenerateapi/settings/otlp_settings.py +69 -0
  62. fastgenerateapi/settings/redis_settings.py +16 -0
  63. fastgenerateapi/settings/sms_settings.py +25 -0
  64. fastgenerateapi/settings/system_settings.py +30 -0
  65. fastgenerateapi/utils/auto_discover.py +61 -0
  66. fastgenerateapi/utils/file_utils.py +76 -0
  67. fastgenerateapi/utils/pwd_utils.py +49 -0
  68. fastgenerateapi/utils/ramdom_utils.py +48 -0
  69. fastgenerateapi/utils/snowflake.py +23 -20
  70. fastgenerateapi/utils/str_util.py +120 -0
  71. fastgenerateapi/utils/swagger_to_js.py +26 -0
  72. {fastgenerateapi-0.0.28.dist-info → fastgenerateapi-1.1.7.dist-info}/METADATA +61 -24
  73. fastgenerateapi-1.1.7.dist-info/RECORD +109 -0
  74. {fastgenerateapi-0.0.28.dist-info → fastgenerateapi-1.1.7.dist-info}/WHEEL +1 -1
  75. {fastgenerateapi-0.0.28.dist-info → fastgenerateapi-1.1.7.dist-info}/top_level.txt +1 -0
  76. script/__init__.py +2 -0
  77. fastgenerateapi/settings/register_settings.py +0 -6
  78. fastgenerateapi/utils/parse_str.py +0 -36
  79. fastgenerateapi-0.0.28.dist-info/RECORD +0 -82
  80. {fastgenerateapi-0.0.28.dist-info → fastgenerateapi-1.1.7.dist-info}/LICENSE +0 -0
@@ -0,0 +1,69 @@
1
+ from typing import Optional
2
+
3
+ import httpx
4
+ from fastapi import FastAPI
5
+ from opentelemetry import metrics, trace
6
+ from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
7
+ from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
8
+ from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
9
+ from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
10
+ from opentelemetry.instrumentation.tortoiseorm import TortoiseORMInstrumentor
11
+ from opentelemetry.sdk.metrics import MeterProvider
12
+ from opentelemetry.sdk.metrics._internal.export import PeriodicExportingMetricReader
13
+ from opentelemetry.sdk.resources import Resource, SERVICE_NAME
14
+ from opentelemetry.sdk.trace import TracerProvider
15
+ from opentelemetry.sdk.trace.export import BatchSpanProcessor
16
+
17
+ from pydantic import Field
18
+ from pydantic_settings import BaseSettings
19
+
20
+
21
+ class OpenTelemetrySettings(BaseSettings):
22
+ """
23
+ 跟踪和指标配置
24
+ """
25
+ ENDPOINT: Optional[str] = Field(default=None, description="访问接口", example="http://127.0.0.1")
26
+ AUTHORIZATION: Optional[str] = Field(default=None, description="认证字符串")
27
+
28
+ def setup_open_telemetry(self, app: FastAPI, service_name: str):
29
+ if not self.ENDPOINT:
30
+ return
31
+
32
+ with httpx.Client() as client:
33
+ health_check = client.get(f"{self.ENDPOINT}/healthz", timeout=3).json()
34
+ if health_check["status"] != "ok":
35
+ raise Exception("otlp服务异常")
36
+ resource = Resource(attributes={
37
+ SERVICE_NAME: service_name
38
+ })
39
+
40
+ tracer_provider = TracerProvider(resource=resource)
41
+ headers = {
42
+ "Authorization": self.AUTHORIZATION} if self.AUTHORIZATION else {}
43
+ exporter = OTLPMetricExporter(
44
+ endpoint=f"{self.ENDPOINT}/api/default/v1/metrics",
45
+ headers=headers,
46
+ )
47
+ meter_provider = MeterProvider([PeriodicExportingMetricReader(exporter)], resource=resource)
48
+ metrics.set_meter_provider(meter_provider)
49
+ processor = BatchSpanProcessor(
50
+ OTLPSpanExporter(
51
+ endpoint=f"{self.ENDPOINT}/api/default/v1/traces",
52
+ headers=headers
53
+ )
54
+ )
55
+ tracer_provider.add_span_processor(processor)
56
+ trace.set_tracer_provider(tracer_provider)
57
+ FastAPIInstrumentor.instrument_app(
58
+ app,
59
+ tracer_provider=tracer_provider,
60
+ meter_provider=meter_provider,
61
+ )
62
+ TortoiseORMInstrumentor().instrument(tracer_provider=tracer_provider)
63
+ HTTPXClientInstrumentor().instrument(tracer_provider=tracer_provider)
64
+
65
+ class Config:
66
+ env_prefix = 'OTLP_'
67
+ env_file = "./.env"
68
+ case_sensitive = True
69
+ extra = 'allow'
@@ -0,0 +1,16 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import Field
4
+ from pydantic_settings import BaseSettings
5
+
6
+
7
+ class RedisSettings(BaseSettings):
8
+ URL: Optional[str] = Field(default="redis://127.0.0.1", description="IP地址")
9
+ PORT: Optional[int] = Field(default=6379, description="映射端口")
10
+ PASSWORD: Optional[str] = Field(default="", description="密码")
11
+
12
+ class Config:
13
+ env_prefix = 'REDIS_'
14
+ env_file = "./.env"
15
+ case_sensitive = True
16
+ extra = 'allow'
@@ -0,0 +1,25 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import Field
4
+ from pydantic_settings import BaseSettings
5
+
6
+
7
+ class SmsSettings(BaseSettings):
8
+ """
9
+ 短信配置
10
+ Sms Settings
11
+ """
12
+ CACHE_BACKEND: Optional[str] = Field(default="redis", description="缓存类型", title="cache_backend(redis, inmemory)")
13
+ CACHE_BACKEND_DSN: Optional[str] = Field(default="redis://localhost:6379/1", description="缓存dsn", title="cache_backend_dsn")
14
+ IS_LIMIT_CODE_FREQUENCY: Optional[bool] = Field(default=True, description="是否限制频率", title="code frequency check")
15
+ CHECK_CODE_RESEND_TIME: Optional[int] = Field(default=1, description="验证码重新发送时间", title="check code resend time (minute)")
16
+ DEFAULT_CODE: Optional[int] = Field(default="654123", description="默认验证码", title="sms default code")
17
+
18
+ class Config:
19
+ env_prefix = 'Sms_'
20
+ env_file = "./.env"
21
+ case_sensitive = True
22
+ extra = 'allow'
23
+
24
+
25
+
@@ -0,0 +1,30 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import Field
4
+ from pydantic_settings import BaseSettings
5
+
6
+
7
+ class SystemSettings(BaseSettings):
8
+ """
9
+ System Settings
10
+ """
11
+ NAME: str = Field(default='fastgenerateapi', description="项目名称")
12
+ HOST: Optional[str] = Field(default='127.0.0.1', description="本地运行host")
13
+ PORT: Optional[int] = Field(default=8001, description="本地运行port")
14
+ DEBUG: bool = Field(default=True, description="是否开启调试模式,本地修改自动重载")
15
+
16
+ # BASE_DIR: Union[PathType, str, None]
17
+ DOMAIN: Optional[str] = Field(default="http://127.0.0.1:8001", description="服务域名(对外暴露的域名地址包含协议)")
18
+ FIELD_SECRET: Optional[str] = Field(default=None, description="字段加密密钥")
19
+
20
+ # 分布式id
21
+ WORKER_ID: Optional[int] = Field(default='1', description="数据中心(机器区域)ID")
22
+ DATACENTER_ID: Optional[int] = Field(default='1', description="机器ID")
23
+
24
+ class Config:
25
+ env_prefix = ''
26
+ env_file = "./.env"
27
+ case_sensitive = True
28
+ extra = 'allow'
29
+
30
+
@@ -0,0 +1,61 @@
1
+ import importlib
2
+ import os
3
+ from pathlib import Path
4
+ from typing import Optional, List
5
+
6
+
7
+ def get_path_list(path: str, match_prefix: str, prefix: str = "") -> List[str]:
8
+ files = []
9
+ prefix = prefix + "." + os.path.basename(path) if prefix else os.path.basename(path)
10
+ for item in Path(path).iterdir():
11
+ if item.is_file():
12
+ if item.name.startswith(match_prefix) and item.name.endswith(".py"):
13
+ files.append(prefix+"."+item.name[:-3])
14
+ elif item.is_dir():
15
+ if item.name.startswith(match_prefix):
16
+ for s_item in Path(os.path.join(path, item.name)).iterdir():
17
+ if s_item.is_file() and s_item.name.startswith(match_prefix):
18
+ files.append(prefix + "." + item.name + "." + s_item.name[:-3])
19
+ else:
20
+ files += get_path_list(os.path.join(path, item.name), match_prefix, prefix)
21
+
22
+ return files
23
+
24
+
25
+ def discover_models(
26
+ base_path="apps", # 模块路径
27
+ include: Optional[List[str]] = None, # 包含的模型
28
+ exclude: Optional[List[str]] = None, # 排除的模型
29
+ ) -> List[str]:
30
+ """
31
+ 自动发现models,并生成tortoise-orm所需要的字符串
32
+ 会自动添加 aerich.models,如不需要请在 exclude 参数排除
33
+ """
34
+ models_list = ["aerich.models"] + get_path_list(base_path, "models")
35
+ return include + [model for model in models_list if model not in exclude] if exclude else models_list
36
+
37
+
38
+ def discover_routes(
39
+ app, # Fastapi 生成的实体类
40
+ base_path="apps", # 模块路径
41
+ prefix="", # 路由前缀
42
+ include: Optional[List[str]] = None, # 包含的路由
43
+ exclude: Optional[List[str]] = None, # 排除的路由
44
+ ):
45
+ """自动发现路由,并注册"""
46
+ paths = include if include else []
47
+
48
+ for path in paths + get_path_list(base_path, "router"):
49
+ if exclude and path in exclude:
50
+ continue
51
+ module = importlib.import_module(path)
52
+ if hasattr(module, "router"):
53
+ app.include_router(prefix=prefix, router=getattr(module, "router"))
54
+ return app
55
+
56
+
57
+ if __name__ == '__main__':
58
+ # print(discover_models("../../modules"))
59
+ print(get_path_list("../../modules", "router"))
60
+
61
+
@@ -0,0 +1,76 @@
1
+ import struct
2
+
3
+ type_dict = {
4
+ # '424D': 'bmp',
5
+ 'FFD8FF': 'jpg',
6
+ # '2E524D46': 'rm',
7
+ # '4D546864': 'mid',
8
+ '89504E47': 'png',
9
+ '47494638': 'gif',
10
+ '49492A00': 'tif',
11
+ # '41433130': 'dwg',
12
+ # '38425053': 'psd',
13
+ # '2142444E': 'pst',
14
+ # 'FF575043': 'wpd',
15
+ # 'AC9EBD8F': 'qdf',
16
+ # 'E3828596': 'pwl',
17
+ '504B0304': 'zip',
18
+ '52617221': 'rar',
19
+ '57415645': 'wav',
20
+ '41564920': 'avi',
21
+ '2E7261FD': 'ram',
22
+ '000001BA': 'mpg',
23
+ '000001B3': 'mpg',
24
+ '6D6F6F76': 'mov',
25
+ # '7B5C727466': 'rtf',
26
+ '3C3F786D6C': 'xml',
27
+ '68746D6C3E': 'html',
28
+ 'D0CF11E0': 'doc/xls',
29
+ '255044462D312E': 'pdf',
30
+ 'CFAD12FEC5FD746F': 'dbx',
31
+ # '3026B2758E66CF11': 'asf',
32
+ '5374616E64617264204A': 'mdb',
33
+ # '252150532D41646F6265': 'ps/eps',
34
+ # '44656C69766572792D646174653A': 'eml'
35
+ }
36
+ max_len = len(max(type_dict, key=len)) // 2
37
+
38
+
39
+ async def get_filetype(file):
40
+ # 读取二进制文件开头一定的长度
41
+ if isinstance(file, str):
42
+ filename = file
43
+ with open(filename, 'rb') as f:
44
+ byte = f.read(max_len)
45
+ else:
46
+ filename = file.filename
47
+ byte = await file.read(max_len)
48
+ await file.seek(0)
49
+ # 解析为元组
50
+ byte_list = struct.unpack('B' * max_len, byte)
51
+ # 转为16进制
52
+ code = ''.join([('%X' % each).zfill(2) for each in byte_list])
53
+ # 根据标识符筛选判断文件格式
54
+ result = list(filter(lambda x: code.startswith(x), type_dict))
55
+ nametype = filename.split('.')[-1]
56
+ if result:
57
+ filetype = type_dict[result[0]]
58
+ if filetype == "zip":
59
+ filetype = nametype if nametype in ['xlsx', 'docx'] else "zip"
60
+ elif filetype == "doc/xls":
61
+ filetype = nametype if nametype in ['doc', 'xls'] else None
62
+ elif filetype == "jpg":
63
+ filetype = nametype if nametype in ['jpg', 'jpeg'] else None
64
+ else:
65
+ filetype = filetype if filetype == nametype else None
66
+ else:
67
+ filetype = nametype if nametype in ['mp3', 'mp4', 'txt'] else None
68
+ return filetype
69
+
70
+ file_type = {
71
+ "image": ["jpg", "png", "gif", "tif"],
72
+ "document": ["zip", "rar", "wav", "xml", "html", "doc", "xls", "pdf", "dbx", "mdb"],
73
+ "voice": ["mp3", "amr"],
74
+ "video": ["wav", "avi", "ram", "mpg", "mov", "mp4"],
75
+ }
76
+
@@ -0,0 +1,49 @@
1
+ import random
2
+
3
+ from passlib.hash import pbkdf2_sha256, md5_crypt
4
+
5
+
6
+ def make_random_salt(length=64):
7
+ """
8
+ 生成随机salt字符串,可指定长度
9
+ :param length: int
10
+ :return: salt: str
11
+ """
12
+ seed = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$&*="
13
+ sa = []
14
+ for i in range(length):
15
+ sa.append(random.choice(seed))
16
+ salt = ''.join(sa)
17
+ return salt
18
+
19
+
20
+ def create_password_hash(password: str, salt: str) -> str:
21
+ """
22
+ 根据传入的password与salt参数生成hash值
23
+ :param password:
24
+ :param salt:
25
+ :return:
26
+ """
27
+ custom_pbkdf2 = pbkdf2_sha256.using(salt=salt.encode('utf-8'), rounds=1000)
28
+ return custom_pbkdf2.hash(password)
29
+
30
+
31
+ def validate_password(password: str, salt: str, password_hash: str) -> bool:
32
+ """
33
+ password 校验
34
+ :param password:
35
+ :param salt:
36
+ :param password_hash:
37
+ :return:
38
+ """
39
+ validating_password_hash = create_password_hash(password, salt)
40
+ return validating_password_hash == password_hash
41
+
42
+
43
+ # if __name__ == '__main__':
44
+ # # salt = make_random_salt(length=60)
45
+ # salt = "lpiZRQwWoj&*wh29Jovk$uA3YGP$TSQYpM4ooy1z3zGuNT=vmLpb&Ves"
46
+ # hash_str = create_password_hash('123456132312312312312321', salt)
47
+ # print(hash_str)
48
+ # print(len(hash_str))
49
+ # print(validate_password(password='123456132312312312312321', salt=salt, password_hash=hash_str))
@@ -0,0 +1,48 @@
1
+ import hashlib
2
+ import random
3
+ import uuid
4
+
5
+
6
+ def get_code(n=4):
7
+ """
8
+ 生成随机验证码,数字和字母的概率各一半
9
+ :param n: 验证码长度
10
+ :return: str
11
+ """
12
+ s = ''
13
+ for i in range(n):
14
+ ret_num = random.randint(0, 9)
15
+ ret_alpha = chr(random.randint(65, 90))
16
+ result = random.choice([ret_num, ret_alpha])
17
+ s += str(result)
18
+ return s
19
+
20
+
21
+ def random_str() -> str:
22
+ """
23
+ 唯一随机字符串
24
+ :return: str
25
+ """
26
+ only = hashlib.md5(str(uuid.uuid1()).encode(encoding='UTF-8')).hexdigest()
27
+ return str(only)
28
+
29
+
30
+ def get_code_number(n: int = 6) -> str:
31
+ """
32
+ 随机数字
33
+ :param n: 长度
34
+ :return: str
35
+ """
36
+ code = ""
37
+ for i in range(n):
38
+ ch = chr(random.randrange(ord('0'), ord('9') + 1))
39
+ code += ch
40
+
41
+ return code
42
+
43
+
44
+ if __name__ == '__main__':
45
+ print(get_code())
46
+ print(random_str())
47
+ print(get_code_number(6))
48
+
@@ -5,7 +5,7 @@ from fastapi.exceptions import RequestValidationError
5
5
 
6
6
 
7
7
  # 64位ID的划分
8
- from fastgenerateapi.settings.register_settings import settings
8
+ from fastgenerateapi.settings.all_settings import settings
9
9
 
10
10
  WORKER_ID_BITS = 5 # 机器位
11
11
  DATACENTER_ID_BITS = 5 # 数据位
@@ -73,30 +73,31 @@ class IdWorker(object):
73
73
  """
74
74
  return int(time.time() * 1000)
75
75
 
76
- def get_post_id(self):
76
+ def get_code(self, prefix: str = ""):
77
77
  """
78
- 获取新ID
78
+ 获取有序编码,高并发不推荐使用,会出现重复值
79
79
  :return:
80
80
  """
81
- timestamp = self._gen_timestamp()
81
+ def make_code():
82
+ timestamp = self._gen_timestamp()
82
83
 
83
- # 时钟回拨
84
- if timestamp < self.last_timestamp:
85
- raise RequestValidationError
84
+ # 时钟回拨
85
+ if timestamp < self.last_timestamp:
86
+ raise RequestValidationError
86
87
 
87
- if timestamp == self.last_timestamp:
88
- self.sequence = (self.sequence + 1) & SEQUENCE_MASK
89
- if self.sequence == 0:
90
- timestamp = self._til_next_millis(self.last_timestamp)
91
- else:
92
- self.sequence = 0
88
+ if timestamp == self.last_timestamp:
89
+ self.sequence = (self.sequence + 1) & 7
90
+ if self.sequence == 0:
91
+ timestamp = self._til_next_millis(self.last_timestamp)
92
+ else:
93
+ self.sequence = 0
93
94
 
94
- self.last_timestamp = timestamp
95
+ self.last_timestamp = timestamp
95
96
 
96
- # new_id = ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT) | (self.datacenter_id << DATACENTER_ID_SHIFT) | \
97
- # (self.worker_id << WOKER_ID_SHIFT) | self.sequence
98
- new_id = ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT) | self.sequence
99
- return 'PT' + str(new_id)
97
+ new_id = (int((timestamp - TWEPOCH) / 100) << 2) | (self.datacenter_id << 2) | \
98
+ (self.worker_id << 2) | self.sequence
99
+ return prefix + str(new_id)
100
+ return make_code
100
101
 
101
102
  def get_id(self):
102
103
  """
@@ -139,8 +140,10 @@ class IdWorker(object):
139
140
  worker = IdWorker(datacenter_id=settings.app_settings.DATACENTER_ID, worker_id=settings.app_settings.WORKER_ID)
140
141
 
141
142
 
142
- # if __name__ == '__main__':
143
- # # worker = IdWorker()
143
+ if __name__ == '__main__':
144
+ # worker = IdWorker()
145
+ print(worker.get_code()())
146
+ print(worker.get_code("A")())
144
147
  # pk = worker.get_id()
145
148
  # print(pk)
146
149
  # print(len(str(pk)), len("9223372036854775807"))
@@ -0,0 +1,120 @@
1
+ from typing import Union, Optional, List
2
+
3
+ from fastgenerateapi.settings.all_settings import settings
4
+
5
+
6
+ def parse_str_to_bool(val: Union[int, str, bool, None]) -> bool:
7
+ """
8
+ 解析字符串到布尔值
9
+ """
10
+ if type(val) == bool:
11
+ return val
12
+ elif type(val) == int:
13
+ return val != 0
14
+ elif type(val) == str:
15
+ if val.upper() in ("1", "ON", "TRUE"):
16
+ return True
17
+ elif val.upper() in ("0", "OFF", "FALSE"):
18
+ return False
19
+ return settings.app_settings.DEFAULT_WHETHER_PAGE
20
+
21
+
22
+ def parse_str_to_int(val: Union[int, str, None]) -> int:
23
+ """
24
+ 解析字符串到数值
25
+ """
26
+ if type(val) == int:
27
+ return val
28
+ elif type(val) == str:
29
+ try:
30
+ val = int(val)
31
+ except Exception as e:
32
+ val = 0
33
+ return val
34
+
35
+ return 0
36
+
37
+
38
+ def parse_str_to_list(val: Optional[str], split_list: Optional[List[str]] = None) -> List[str]:
39
+ """
40
+ 某些字段可能由、,,等拼接,字符串分割为列表
41
+ :param val: 我、你,他,她
42
+ :param split_list: 默认 ["、", ",", ","]
43
+ :return: ["我", "你", "他", "她"]
44
+ """
45
+ # 如果输入为空,返回空列表
46
+ if not val:
47
+ return []
48
+
49
+ # 设置默认分隔符列表
50
+ if split_list is None:
51
+ split_list = ["、", ",", ","]
52
+
53
+ # 初始化结果列表
54
+ result = [val]
55
+
56
+ # 遍历分隔符,逐步拆分字符串
57
+ for sep in split_list:
58
+ result = [item for sublist in result for item in sublist.split(sep)]
59
+
60
+ # 去除每个元素的前后空格
61
+ result = [item.strip() for item in result]
62
+
63
+ # 过滤掉空字符串
64
+ result = [item for item in result if item]
65
+
66
+ return result
67
+
68
+
69
+ def number_to_chinese(num):
70
+ """
71
+ 数字转换为大写中文,会自动带上整字
72
+ :param num:
73
+ :return:
74
+ """
75
+ if num == 0:
76
+ return "零元整"
77
+ dict1 = {1: '壹', 2: '贰', 3: '叁', 4: '肆', 5: '伍', 6: '陆', 7: '柒', 8: '捌', 9: '玖', 0: '零'}
78
+ dict2 = {2: '拾', 3: '佰', 4: '仟', 5: '万', 6: '拾', 7: '佰', 8: '仟', 1: '元', 9: '角', 10: '分', 11: '整'}
79
+ money = ''
80
+ flag = False
81
+ flag2 = False
82
+ count = 0
83
+ count2 = 8
84
+ strnum = str(num)
85
+ aa = strnum.split('.')
86
+ bb = list(str(aa[:1])[2:-2])
87
+ cc = list(str(aa[1]).rstrip("0")[:2]) if len(aa) > 1 else []
88
+
89
+ for i in reversed(bb):
90
+ count = count + 1
91
+ if int(i) == 0:
92
+ if flag:
93
+ if count != 5:
94
+ continue
95
+ else:
96
+ money = dict2[count] + money
97
+ else:
98
+ if not flag2:
99
+ money = dict2[count] + money
100
+ else:
101
+ if count != 5:
102
+ money = '零' + money
103
+ else:
104
+ money = dict2[count] + '零' + money
105
+ flag = True
106
+ else:
107
+ flag = False
108
+ flag2 = True
109
+ money = dict1[int(i)] + dict2[count] + money
110
+ for i in cc:
111
+ count2 = count2 + 1
112
+ money = money + dict1[int(i)] + dict2[count2]
113
+
114
+ return money + '整'
115
+
116
+
117
+ if __name__ == '__main__':
118
+ # test parse_str_to_list
119
+ print(parse_str_to_list("我、你,他,她"))
120
+ print(parse_str_to_list("我|你&他 她", split_list=["|", "&", " "]))
@@ -0,0 +1,26 @@
1
+ from typing import Optional
2
+
3
+
4
+ class SwaggerUtil:
5
+
6
+ @staticmethod
7
+ def swagger_to_js(swagger_json: Optional[dict]):
8
+ """
9
+ 通过swagger文档自动生成js接口文件,方便前后端开发
10
+ 如果 swagger_json 为空,
11
+ - 优先检查运行路径下的swagger.json文件
12
+ - 其次检查 127.0.0.1:8000/openapi.json 接口
13
+ :param swagger_json:
14
+ :return:
15
+ """
16
+ # 参考go zero 生成js文件的样式
17
+
18
+ return
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+