From 750de0a9ce7811b06ffaeed7ffdda078dd6aefb8 Mon Sep 17 00:00:00 2001 From: mnjnhuang <1090031856@qq.com> Date: Wed, 19 Mar 2025 18:00:58 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=81=E7=A7=BBGit=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 163 ++++++++++++++++ README.md | 4 + framework/m_mysql_cli.py | 136 +++++++++++++ framework/main_framework.py | 39 ++++ framework/open_response.py | 88 +++++++++ framework/requests_dataclass.py | 44 +++++ framework/response_code.py | 39 ++++ framework/sample_requests.py | 133 +++++++++++++ framework/test.py | 10 + main.py | 32 ++++ requirement | 3 + router/datacenter/__init__.py | 6 + router/datacenter/resources/__init__.py | 6 + .../resources/datacenter/__init__.py | 6 + .../datacenter/get_datacenter_table.py | 179 ++++++++++++++++++ router/mains/__init__.py | 7 + router/mains/login_username.py | 108 +++++++++++ 17 files changed, 1003 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 framework/m_mysql_cli.py create mode 100644 framework/main_framework.py create mode 100644 framework/open_response.py create mode 100644 framework/requests_dataclass.py create mode 100644 framework/response_code.py create mode 100644 framework/sample_requests.py create mode 100644 framework/test.py create mode 100644 main.py create mode 100644 requirement create mode 100644 router/datacenter/__init__.py create mode 100644 router/datacenter/resources/__init__.py create mode 100644 router/datacenter/resources/datacenter/__init__.py create mode 100644 router/datacenter/resources/datacenter/get_datacenter_table.py create mode 100644 router/mains/__init__.py create mode 100644 router/mains/login_username.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e2c30b5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,163 @@ +# ---> Python +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class +framework/server_config.py +# C extensions +*.so + +# Distribution / packaging +.Python +.idea/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +.idea/ + diff --git a/README.md b/README.md new file mode 100644 index 0000000..6d02a38 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# Flask +Flask is a lightweight WSGI web application framework. It is designed to make getting started quick and easy, with the ability to scale up to complex applications. It began as a simple wrapper around Werkzeug and Jinja, and has become one of the most popular Python web application frameworks. + +Flask offers suggestions, but doesn't enforce any dependencies or project layout. It is up to the developer to choose the tools and libraries they want to use. There are many extensions provided by the community that make adding new functionality easy. \ No newline at end of file diff --git a/framework/m_mysql_cli.py b/framework/m_mysql_cli.py new file mode 100644 index 0000000..c1ecf88 --- /dev/null +++ b/framework/m_mysql_cli.py @@ -0,0 +1,136 @@ +import pymysql +from framework.server_config import ServerConfig +import copy +from framework.open_response import MinCustomException +from framework.response_code import ResponseCode + + +class MysqlCli(ServerConfig): + def __init__(self): + super().__init__() + self._sql = None + # 连接 + self._connect = self._connect_mysql() + # 游标 + self._cursor = self._connect.cursor() + # response message + self._sql_response: dict = {"Status": False, + "Result": None, + "Execute_sql": None, + "Exception_error": None} + + def _connect_mysql(self, need_character: bool = False): + if need_character: + return pymysql.connect(host=self.mysql_host, + user=self.mysql_user, + password=self.mysql_password, + database=self.mysql_database, + charset=self.mysql_character, + port=self.mysql_port) + else: + return pymysql.connect(host=self.mysql_host, + user=self.mysql_user, + password=self.mysql_password, + database=self.mysql_database, + port=self.mysql_port) + + def commit_all(self, debug: bool = False, please_commit: bool = True) -> dict: + _result = copy.deepcopy(self._sql_response) + if not self._sql: + _result.update({"result": "Execute_SQL Is Null! " + "\nPlease Run 'self.create_sql(sql:str)'", + "Execute_sql": self._sql}) + self.call_print_result(_result) + return _result + + try: + self._cursor.execute(self._sql) + if please_commit: + self._connect.commit() + _result.update({"Status": True, + "Result": "Commit Success!"}) + + except Exception as error: + self._connect.rollback() + _result.update({"Result": "Commit Exception! RollBack", + "Exception_error": error}) + self.call_print_result(_result) + + finally: + self.flush_sql() + return _result + + def fetchone(self, debug: bool = False, fetchall: bool = False) -> dict: + _result = copy.deepcopy(self._sql_response) + if not self._sql: + _result.update({"Result": "Execute_SQL Is Null! " + "\nPlease Run 'self.create_sql(sql:str)'"}) + self.call_print_result(_result) + return _result + _result.update({"Execute_sql": self._sql}) + try: + self._cursor.execute(self._sql) + + if not fetchall: + _result.update({"Result": self._cursor.fetchone(), + "Status": True}) + else: + _result.update({"Result": self._cursor.fetchall(), + "Status": True}) + except Exception as error: + _result.update({"Exception_error": error}) + self.call_print_result(_result) + finally: + self.flush_sql() + return _result + + def flush_sql(self): + self._sql = None + + def create_sql(self, sql: str): + self._sql = sql + + def ping_connect(self): + self._connect.ping(True) + + def close_connect(self): + if self._cursor: + self._cursor.close() + if self._connect: + self._connect.close() + + @staticmethod + def call_result(result): + print(result) + return result["Result"] + + @staticmethod + def call_status(result): + return result["Status"] + + @staticmethod + def call_execute_sql(result): + return result["Execute_sql"] + + @staticmethod + def call_exception_error(result): + return result["Exception_error"] + + @staticmethod + def call_print_result(result): + print("-" * 50) + print("Database Error:") + for key, value in result.items(): + print(f"{key}: {value}") + + def check_mysql_exception(self, mysql_result: dict, print_result: bool = False): + if not self.call_status(mysql_result): + if print_result: + self.call_print_result(mysql_result) + raise MinCustomException(ResponseCode.RESPONSE_501_NOT_IMPLEMENTED_EXCEPTION) + + def check_mysql_response_null(self, mysql_result: dict, print_result: bool = False): + if not self.call_result(mysql_result): + if print_result: + self.call_print_result(mysql_result) + raise MinCustomException(ResponseCode.RESPONSE_501_NOT_IMPLEMENTED_NULL) diff --git a/framework/main_framework.py b/framework/main_framework.py new file mode 100644 index 0000000..94b475c --- /dev/null +++ b/framework/main_framework.py @@ -0,0 +1,39 @@ +from framework.open_response import OpenResponse +from abc import abstractmethod +from time import sleep +import json +from framework.open_response import MinCustomException + + +class Response(OpenResponse): + """必须实现Core和Before_Response方法""" + + def __init__(self): + super(Response, self).__init__() + + @abstractmethod + def core(self) -> None: + # TODO: 用于处理核心内容, 数据库逻辑等 + pass + + @abstractmethod + def before_response(self) -> dict: + # TODO: 用于创建返回的内容, 以及关闭数据库连接等 + pass + + +def main_function(response: Response) -> dict: + """ + :param response: 重写的Response类 + """ + try: + response.core() + except json.decoder.JSONDecodeError: + response.build_response_code(response.response_code_enum.RESPONSE_400_BAD_REQUESTS_JSON) + sleep(1) + response.echo = True + except MinCustomException as e: + response.build_response_code(e.args[0]) + sleep(1) + response.echo = True + return response.before_response() diff --git a/framework/open_response.py b/framework/open_response.py new file mode 100644 index 0000000..9addf71 --- /dev/null +++ b/framework/open_response.py @@ -0,0 +1,88 @@ +from abc import ABC +from framework.response_code import ResponseCode +from datetime import datetime +from flask import request +import hashlib + + +class MinCustomException(Exception): + def __init__(self, error): + self.error = error + super().__init__(self.error) + + +class OpenABC(ABC): + """ + 提供公共函数和功能函数 + """ + + def __init__(self): + self.response_code_enum: ResponseCode = ResponseCode + + @staticmethod + def call_datetime(need_str: bool = True): + return str(datetime.now()) if need_str else datetime.now() + + @staticmethod + def md5sum(string: str): + md5 = hashlib.md5() + password = string.encode("utf-8") + md5.update(password) + return md5.hexdigest() + + @staticmethod + def make_exception(error_code: ResponseCode): + raise MinCustomException(error_code) + + +class OpenResponse(OpenABC): + def __init__(self): + super(OpenResponse, self).__init__() + self._response_code = self.response_code_enum.RESPONSE_100_CONTINUE # 错误代码, 默认Continue + + self._response_data = None # 返回的数据 + + self.response: dict = {} + + self.echo = False # 是否打印消息 + + # def make_logging(self): + # request_url: str = request.url + # if self.response_code == self.response_code_enum.RESPONSE_200_SUCCESS: + # self.log_access(f"{request_url}\n{self.response}\n") + # else: + # self.log_error(f"{request_url}\n{self.response}\n") + + def make_response(self) -> dict: + response_code: ResponseCode = self._response_code + + err_code, err_message = response_code.return_tuple() + self.response = {"code": err_code, "message": err_message} + + if self._response_data is not None: + self.response.update({"data": self._response_data}) + + if self.echo is True: + print("-" * 50) + print("Interface ERROR:") + print(f"Echo url: {request.url}") + print(f"Echo methods: {request.method}") + if request.method == "GET": + print(f"Echo params: {request.args}") + elif request.method == "POST": + print(f"Echo data: {request.data}") + print(f"Echo response: {self.response}") + return self.response + + def build_response_data(self, data: object): + """ + 生成response_data + :return: + """ + self._response_data = data + + def build_response_code(self, code_enum: ResponseCode): + self._response_code = code_enum + + def make_debug_response(self): + raise MinCustomException(self.response_code_enum.RESPONSE_201_DEBUG) diff --git a/framework/requests_dataclass.py b/framework/requests_dataclass.py new file mode 100644 index 0000000..301a19e --- /dev/null +++ b/framework/requests_dataclass.py @@ -0,0 +1,44 @@ +from dataclasses import dataclass +import json as JSON +from flask import request + +from framework.open_response import OpenABC +from framework.response_code import RequestMethods + + +@dataclass +class SampleRequests(OpenABC): + """ + 基本数据请求体 + login_username: str + login_password: str + self.login_username = self.check_string(self.json_data.get("login_username")) + self.login_password = self.check_string(self.json_data.get("login_token")) + """ + + def __init__(self, methods: RequestMethods, json_data: bytes | str | dict): + """ + :param methods: 请求方式, 需要传入枚举类型的数据 + :param json_data: 请求的数据, 如果是POST请求, 则为bytes|str类型 + 如果是GET请求, 则为dict类型 + """ + super().__init__() + if methods != RequestMethods.POST and methods != RequestMethods.GET: + self.make_exception(self.response_code_enum.RESPONSE_405_METHODS_NOT_ALLOW) + if methods == RequestMethods.POST: + self.json_data: dict = JSON.loads(json_data) + elif methods == RequestMethods.GET: + self.json_data = json_data + + def repr(self): + print(self.__repr__()) + + @staticmethod + def return_headers(): + return request.headers + + def return_token(self) -> str: + authorization = request.headers.get("Authorization") + if authorization and authorization.startswith("Bearer"): + return authorization.replace("Bearer ", "") + self.make_exception(self.response_code_enum.RESPONSE_401_TOKEN_INVALID) diff --git a/framework/response_code.py b/framework/response_code.py new file mode 100644 index 0000000..256959b --- /dev/null +++ b/framework/response_code.py @@ -0,0 +1,39 @@ +from enum import unique +from enum import Enum + + +@unique +class RequestMethods(Enum): + GET = 1 + POST = 2 + PUT = 3 + DELETE = 4 + + +@unique +class ResponseCode(Enum): + def __init__(self, code: int, message: str) -> None: + self.code: int = code + self.message: str = message + + # Main + RESPONSE_100_CONTINUE = 100, "Continue" + RESPONSE_200_SUCCESS = 200, "Success" + RESPONSE_201_DEBUG = 201, "Debug" + RESPONSE_502_BAD_GATEWAY = 502, "BadGateway" + RESPONSE_500_SERVER_ERROR = 500, "ServerError" + RESPONSE_405_METHODS_NOT_ALLOW = 405, "METHODS NOT ALLOW" + RESPONSE_501_NOT_IMPLEMENTED_EXCEPTION = 501.1, "NOT IMPLEMENTED" # 数据库语句异常 + RESPONSE_501_NOT_IMPLEMENTED_NULL = 501.2, "NOT IMPLEMENTED" # 数据库语句异常 + + RESPONSE_400_BAD_REQUESTS_JSON = 400.1, "JsonDecodeError" + RESPONSE_401_Unauthorized = 401, "Unauthorized" + RESPONSE_401_TOKEN_INVALID = 401.1, "TokenInvalid" + RESPONSE_401_TOKEN_EXPIRE = 401.2, "TokenExpire" + + # Request Params Warning + RESPONSE_PARAMS_IS_NULL = 10400, "未获取所有参数" + RESPONSE_PARAMS_IS_VALID = 10401, "请求参数错误" + + def return_tuple(self) -> tuple: + return self.code, self.message diff --git a/framework/sample_requests.py b/framework/sample_requests.py new file mode 100644 index 0000000..c45fdf3 --- /dev/null +++ b/framework/sample_requests.py @@ -0,0 +1,133 @@ +from framework.main_framework import Response, main_function +from framework.requests_dataclass import SampleRequestsGET, SampleRequestsPOST +from dataclasses import dataclass +from dataclasses import asdict +from flask import Blueprint +from flask import request +from framework.m_mysql_cli import MysqlCli + + +@dataclass +class OverrideRequestsPOST(SampleRequestsPOST): + """ + 创建POST请求参数 + """ + + def __init__(self): + super(OverrideRequestsPOST, self).__init__(json_data=request.get_data()) + + +@dataclass +class OverrideRequestsGET(SampleRequestsGET): + """ + 创建GET请求参数 + """ + + def __init__(self): + super(OverrideRequestsGET, self).__init__(json_data=request.args) + + +@dataclass +class ResponseInterface: + """ + 返回的内容 + """ + + def convert_to_dict(self) -> dict: + """ + 调用这个函数将ResponseInterface数据类转成字典类型的数据 + :return: dict + """ + return asdict(self) + + +class OverrideMysqlCli(MysqlCli): + """ + 创建Mysql操作类 + """ + + def __init__(self): + super(OverrideMysqlCli, self).__init__() + self.token_table = "accounts_info" + + def handle_search_token_valid(self, username: str, user_token: str) -> None: + # 验证登录token + sql = f""" + SELECT + username + FROM {self.token_table} + WHERE username = '{username}' AND user_token = '{user_token} AND 1=1' + """ + self.create_sql(sql) + mysql_result: dict = self.fetchone() + self.check_mysql_exception(mysql_result=mysql_result) + self.check_mysql_response_null(mysql_result=mysql_result) + + +class OverriderMainResponse(Response): + """ + 主要处理请求的类 + """ + + def __init__(self, connect_mysql: bool = True): + super(OverriderMainResponse, self).__init__() + self.is_connect_mysql = connect_mysql + # 返回的数据 + + # 是否连接数据库 + if self.is_connect_mysql: + self.mysql_cli: OverrideMysqlCli = OverrideMysqlCli() + + # 是否处理成功 + self.handle_success: bool = False + + def core(self) -> None: + """ + 重写core函数处理核心内容 例如数据查询/数据处理 + """ + params = OverrideRequestsGET() + params = OverrideRequestsPOST() + + """ + 处理完核心内容后将 handle_success 设置为True + self.handle_success = True + """ + # self.handle_success = True + if self.handle_success: + self.build_response_code(self.response_code_enum.RESPONSE_200_SUCCESS) + + """ + 请不要忘记将想要返回的内容赋予 self.build_response_data(object) + """ + + def before_response(self) -> dict: + """ + 重写before_response函数 + 例如关闭mysql/redis连接等 + """ + if self.is_connect_mysql: + self.mysql_cli.close_connect() + + return self.make_response() + + +""" +请不要忘记生成Flask蓝图 +""" +sample_interface = Blueprint("sample_interface", __name__) + +""" +请不要忘记指定URL路径 +请不要忘记执行main_function函数 +""" + + +@sample_interface.route("/sample/index", methods=["GET"]) +def main(): + """ + 实例化OverrideMainResponse类 并传入main_function中 + 您只重写core()和before_response() + 即可完成一个接口 它将返回一个dict直接发送给请求端 + """ + override_main_response = OverriderMainResponse() + return main_function(override_main_response) diff --git a/framework/test.py b/framework/test.py new file mode 100644 index 0000000..01c787e --- /dev/null +++ b/framework/test.py @@ -0,0 +1,10 @@ +from open_response import OpenABC + +# x = OpenABC() +# print(x.md5sum("admin")) + +import requests + +html = requests.post(url="http://localhost:5000/main/login", data={"username": "admin", + "password": "admin"}) +print(html.text) diff --git a/main.py b/main.py new file mode 100644 index 0000000..5dc7a04 --- /dev/null +++ b/main.py @@ -0,0 +1,32 @@ +from flask import Flask +from flask import abort +from flask_cors import CORS + +from framework.server_config import ServerEnv +from framework.server_config import ServerConfig + +from router.mains import register_blueprints as register_blueprints_main +from router.datacenter import register_blueprints as register_blueprints_datacenter + +app = Flask(__name__) +CORS(app, supports_credentials=True) + +register_blueprints_main(app) +register_blueprints_datacenter(app) + + +@app.route("/") +def hello_world(): + return abort(500) + + +server: ServerConfig = ServerConfig() + +if server.tell_env() != ServerEnv.BUILD: + # 开启计划任务 + pass + +if __name__ == '__main__': + server_listen: tuple = server.tell_listen() + app.run(host=server_listen[0], port=server_listen[1], + debug=True if server.tell_env() == ServerEnv.DEBUG else False) diff --git a/requirement b/requirement new file mode 100644 index 0000000..4effb5d --- /dev/null +++ b/requirement @@ -0,0 +1,3 @@ +flask +flask-cors +hashlib diff --git a/router/datacenter/__init__.py b/router/datacenter/__init__.py new file mode 100644 index 0000000..0974300 --- /dev/null +++ b/router/datacenter/__init__.py @@ -0,0 +1,6 @@ +from .resources import register_blueprints_resources as register_resources_bp +from flask import Flask + + +def register_blueprints(app: Flask): + register_resources_bp(app, url_prefix=f"/datacenter") diff --git a/router/datacenter/resources/__init__.py b/router/datacenter/resources/__init__.py new file mode 100644 index 0000000..1a6f1ca --- /dev/null +++ b/router/datacenter/resources/__init__.py @@ -0,0 +1,6 @@ +from .datacenter import register_blueprints as register_datacenter_bp +from flask import Flask + + +def register_blueprints_resources(app: Flask, url_prefix: str): + register_datacenter_bp(app, url_prefix=f"{url_prefix}/resources") diff --git a/router/datacenter/resources/datacenter/__init__.py b/router/datacenter/resources/datacenter/__init__.py new file mode 100644 index 0000000..a30fd6b --- /dev/null +++ b/router/datacenter/resources/datacenter/__init__.py @@ -0,0 +1,6 @@ +from .get_datacenter_table import datacenter_resources_datacenter_interface as datacenter_bp +from flask import Flask + + +def register_blueprints(app: Flask, url_prefix: str): + app.register_blueprint(datacenter_bp, url_prefix=f"{url_prefix}/datacenter") diff --git a/router/datacenter/resources/datacenter/get_datacenter_table.py b/router/datacenter/resources/datacenter/get_datacenter_table.py new file mode 100644 index 0000000..1d7ff2a --- /dev/null +++ b/router/datacenter/resources/datacenter/get_datacenter_table.py @@ -0,0 +1,179 @@ +from framework.main_framework import Response, main_function +from framework.requests_dataclass import SampleRequests +from dataclasses import dataclass +from dataclasses import asdict +from flask import Blueprint +from flask import request +from framework.m_mysql_cli import MysqlCli +from framework.response_code import RequestMethods + + +@dataclass +class OverrideRequestsGET(SampleRequests): + username: str + user_token: str + table_page: int + + def __init__(self): + super(OverrideRequestsGET, self).__init__(json_data=request.args, methods=RequestMethods.GET) + self.username = self.json_data.get("username") + _table_page: str = self.json_data.get("table_page") + self.user_token = self.return_token() + if not self.username or \ + not _table_page or \ + not self.user_token or \ + not _table_page.isdigit(): + self.make_exception(self.response_code_enum.RESPONSE_400_BAD_REQUESTS_JSON) + + self.table_page = int(_table_page) + + +@dataclass +class ResponseItem: + id: int + code: str + vendor: str + model: str + kind: str + mac: str + status: int + address: str + + +@dataclass +class ResponseInterface: + data: list[ResponseItem] + + def convert_to_dict(self) -> dict: + return asdict(self) + + +class OverrideMysqlCli(MysqlCli): + def __init__(self): + super(OverrideMysqlCli, self).__init__() + self.page_table = "resources_datacenter" + self.map_table = "resources_mapping_relation" + self.token_table = "accounts_info" + + def handle_search_token_valid(self, username: str, user_token: str) -> None: + # 验证登录token + sql = f""" + SELECT + username + FROM {self.token_table} + WHERE username = '{username}' AND user_token = '{user_token} AND 1=1' + """ + self.create_sql(sql) + mysql_result: dict = self.fetchone() + self.check_mysql_exception(mysql_result=mysql_result) + self.check_mysql_response_null(mysql_result=mysql_result) + + def handle_search_table_page(self, page: int) -> dict: + # 查询数据 + sql = f""" + SELECT + id, device_model, device_kind, device_ipaddress, device_status, device_code, + device_mac, vendor_id + FROM {self.page_table} WHERE 1=1 + LIMIT {(page - 1) * 10}, 10 + """ + self.create_sql(sql) + mysql_result: dict = self.fetchone(fetchall=True) + self.check_mysql_exception(mysql_result=mysql_result) + return mysql_result + + def handle_search_table_map(self) -> dict: + # 查询映射表 + sql = f""" + SELECT + encoding_key, encoding_value, encoding_value1 + FROM {self.map_table} + WHERE 1=1 AND + encoding_type = 'vendor' + """ + self.create_sql(sql) + mysql_result: dict = self.fetchone(fetchall=True) + self.check_mysql_exception(mysql_result=mysql_result) + return mysql_result + + +class OverriderMainResponse(Response): + """ + 主要处理请求的类 + """ + + def __init__(self, connect_mysql: bool = True): + super(OverriderMainResponse, self).__init__() + self.is_connect_mysql = connect_mysql + # 返回的数据 + + # 是否连接数据库 + if self.is_connect_mysql: + self.mysql_cli: OverrideMysqlCli = OverrideMysqlCli() + + # 是否处理成功 + self.handle_success: bool = False + + def core(self) -> None: + """ + 重写core函数处理核心内容 例如数据查询/数据处理 + """ + params = OverrideRequestsGET() + + data_result: dict = self.mysql_cli.handle_search_table_page(params.table_page) + map_result: dict = self.mysql_cli.handle_search_table_map() + self.mysql_cli.call_print_result(map_result) + for item in self.mysql_cli.call_result(data_result): + response_item: ResponseItem = ResponseItem(code=item[5], + model=item[1], + kind=item[2], + address=item[3], + mac=item[6], + vendor=item[7], + id=item[0], + status=item[4]) + print(response_item.__repr__()) + """ + 处理完核心内容后将 handle_success 设置为True + self.handle_success = True + """ + # self.build_response_data(result) + # self.handle_success = True + if self.handle_success: + self.build_response_code(self.response_code_enum.RESPONSE_200_SUCCESS) + + """ + 请不要忘记将想要返回的内容赋予 self.build_response_data(object) + """ + + def before_response(self) -> dict: + """ + 重写before_response函数 + 例如关闭mysql/redis连接等 + """ + if self.is_connect_mysql: + self.mysql_cli.close_connect() + + return self.make_response() + + +""" +请不要忘记生成Flask蓝图 +""" +datacenter_resources_datacenter_interface = Blueprint("datacenter_resources_datacenter_interface", __name__) + +""" +请不要忘记指定URL路径 +请不要忘记执行main_function函数 +""" + + +@datacenter_resources_datacenter_interface.route("/page", methods=["GET"]) +def main(): + """ + 实例化OverrideMainResponse类 并传入main_function中 + 您只重写core()和before_response() + 即可完成一个接口 它将返回一个dict直接发送给请求端 + """ + override_main_response = OverriderMainResponse() + return main_function(override_main_response) diff --git a/router/mains/__init__.py b/router/mains/__init__.py new file mode 100644 index 0000000..688a72e --- /dev/null +++ b/router/mains/__init__.py @@ -0,0 +1,7 @@ +from flask import Blueprint +from flask.app import Flask +from .login_username import login_bp + + +def register_blueprints(app: Flask): + app.register_blueprint(login_bp, url_prefix="/main") diff --git a/router/mains/login_username.py b/router/mains/login_username.py new file mode 100644 index 0000000..6b6d89d --- /dev/null +++ b/router/mains/login_username.py @@ -0,0 +1,108 @@ +from dataclasses import asdict +from framework.main_framework import Response, main_function +from framework.requests_dataclass import SampleRequests +from dataclasses import dataclass +from flask import Blueprint +from flask import request +from framework.m_mysql_cli import MysqlCli +from framework.response_code import RequestMethods + + +@dataclass +class OverrideRequestsPOST(SampleRequests): + username: str + password: str + + def __init__(self): + super(OverrideRequestsPOST, self).__init__(json_data=request.get_data(), methods=RequestMethods.POST) + self.username = self.json_data.get("username") + self.password = self.json_data.get("password") + if not self.username or not self.password: + self.make_exception(self.response_code_enum.RESPONSE_PARAMS_IS_VALID) + + +@dataclass +class ResponseInterface: + username: str + user_token: str + + def convert_to_dict(self) -> dict: + return asdict(self) + + +class OverrideMysqlCli(MysqlCli): + """ + 创建Mysql操作类 + """ + + def __init__(self): + super(OverrideMysqlCli, self).__init__() + self.table = "accounts_info" + + def handle_search_password(self, params: OverrideRequestsPOST) -> dict: + sql: str = f"SELECT username, password FROM {self.table} WHERE username='{params.username}' AND 1=1" + self.create_sql(sql) + mysql_result: dict = self.fetchone(fetchall=True) + self.check_mysql_exception(mysql_result=mysql_result) + return mysql_result + + def handle_update_token(self, data: ResponseInterface) -> None: + sql: str = f"UPDATE {self.table} SET token='{data.user_token}' WHERE username='{data.username}'" + self.create_sql(sql) + mysql_result = self.commit_all(please_commit=True) + self.check_mysql_exception(mysql_result=mysql_result) + + +class OverriderMainResponse(Response): + def __init__(self, connect_mysql: bool = True): + super(OverriderMainResponse, self).__init__() + self.is_connect_mysql = connect_mysql + + # 是否连接数据库 + if self.is_connect_mysql: + self.mysql_cli: OverrideMysqlCli = OverrideMysqlCli() + + # 是否处理成功 + self.handle_success: bool = False + + def core(self) -> None: + params = OverrideRequestsPOST() + mysql_result = self.mysql_cli.handle_search_password(params=params) + + if not self.mysql_cli.call_result(mysql_result): + self.make_exception(self.response_code_enum.RESPONSE_401_Unauthorized) + + form_password = self.md5sum(params.password) + mysql_password = self.mysql_cli.call_result(mysql_result)[0][1] + + if form_password != mysql_password: + self.make_exception(self.response_code_enum.RESPONSE_401_Unauthorized) + create_token: str = self.md5sum(f"{mysql_password}+{self.call_datetime(need_str=True)}") + + response_interface: ResponseInterface = ResponseInterface(username=params.username, + user_token=create_token) + self.mysql_cli.handle_update_token(data=response_interface) + + self.handle_success = True + if self.handle_success: + response_data: dict = response_interface.convert_to_dict() + self.build_response_data(response_data) + self.build_response_code(self.response_code_enum.RESPONSE_200_SUCCESS) + + def before_response(self) -> dict: + if self.response == self.response_code_enum.RESPONSE_200_SUCCESS: + pass + + if self.is_connect_mysql: + self.mysql_cli.close_connect() + + return self.make_response() + + +login_bp = Blueprint("login_bp", __name__) + + +@login_bp.route("/login", methods=["POST"]) +def main(): + override_main_response = OverriderMainResponse() + return main_function(override_main_response)