From ba1808fd3f2958de9bbef85a485b011f874f31d8 Mon Sep 17 00:00:00 2001 From: flaskfarm Date: Wed, 12 Oct 2022 15:40:54 +0900 Subject: [PATCH] 3.10 --- files/config.yaml.template | 16 ++++++++------ files/requirements.txt | 2 +- lib/framework/init_main.py | 36 ++++++++++++++++++++++++------- lib/framework/init_plugin.py | 6 ++++-- lib/framework/templates/base.html | 3 ++- lib/plugin/logic.py | 13 ++++++----- lib/plugin/model_setting.py | 29 ++++++++++++++----------- 7 files changed, 67 insertions(+), 38 deletions(-) diff --git a/files/config.yaml.template b/files/config.yaml.template index 66b8501..95b250b 100644 --- a/files/config.yaml.template +++ b/files/config.yaml.template @@ -1,8 +1,16 @@ +path_data: "." +#path_plugins_dev: + + # 데이터 폴더 루트 경로 # 윈도우의 경우 폴더 구분 기호 \ 를 두개 사용 # 예) data_folder: "C:\\work\\data" # 현재 폴더인 경우 . -path_data: "." +#path_data: "." +#path_data: "/mnt/c/work/FlaskFarm/working" + +# 개발용 플러그인 경로 +#path_plugins_dev: #path_data: "/mnt/c/work/FlaskFarm/working" # gevent 사용여부 @@ -10,7 +18,6 @@ path_data: "." # 실행환경에 gevent 관련 패키지가 설치되어 있지 않는다면 값과 상관 없이 false로 동작. #use_gevent: true - # celery 사용 여부 #use_celery: true @@ -33,21 +40,18 @@ path_data: "." # - debug 값이 true인 경우에는 항상 false #plugin_update: true - # running_type # termux, entware 인 경우 입력 함. #running_type: "native" - # 개발용 폴더만 로딩할 경우 사용 #plugin_loading_only_devpath: true - # 로딩할 플러그인 package 명 # 타 플러그인과 연동되는 플러그인 개발시 사용. # import 로 런타임에 로딩할 수 있지만 타 패키지 메뉴 등은 표시되지 않음. #plugin_loading_list: ['command', 'flaskcode'] - + # 로딩 제외할 플러그인 package 명 #plugin_except_list: ['terminal', 'membership'] diff --git a/files/requirements.txt b/files/requirements.txt index 30be613..de630ae 100644 --- a/files/requirements.txt +++ b/files/requirements.txt @@ -1,6 +1,6 @@ #flask Flask==1.1.1 -Flask-SQLAlchemy +Flask-SQLAlchemy==2.5.1 Flask-Login==0.4.1 Flask-Cors==3.0.8 Flask-Markdown diff --git a/lib/framework/init_main.py b/lib/framework/init_main.py index b6fb2a7..7d24ab2 100644 --- a/lib/framework/init_main.py +++ b/lib/framework/init_main.py @@ -67,7 +67,8 @@ class Framework: self.app = Flask(__name__) self.__config_initialize('flask') - self.db = SQLAlchemy(self.app, session_options={"autoflush": False}) + self.__init_db() + if True or self.config['run_flask']: from .scheduler import Job, Scheduler @@ -96,7 +97,29 @@ class Framework: #DROPZONE_ALLOWED_FILE_TYPE = 'default, image, audio, video, text, app, *.*', ) self.dropzone = Dropzone(self.app) + + + def __init_db(self): + # https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/config/#flask_sqlalchemy.config.SQLALCHEMY_BINDS + # 어떤 편법도 불가. db를 사용하지 않아도 파일이 생김. + db_path = os.path.join(self.config['path_data'], 'db', 'system.db') + self.app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{db_path}' # 3.0에서 필수 + self.app.config['SQLALCHEMY_BINDS'] = {'system':f'sqlite:///{db_path}'} + self.app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False + + _ = os.path.join(self.config['path_data'], 'plugins') + plugins = [] + if os.path.exists(_): + plugins = os.listdir(_) + if self.config['path_plugins_dev'] != None and os.path.exists(self.config['path_plugins_dev']): + plugins += os.listdir(self.config['path_plugins_dev']) + + for package_name in plugins: + db_path = os.path.join(self.config['path_data'], 'db', f'{package_name}.db') + self.app.config['SQLALCHEMY_BINDS'][package_name] = f'sqlite:///{db_path}' + self.db = SQLAlchemy(self.app, session_options={"autoflush": False}) + def __init_celery(self): try: @@ -158,7 +181,8 @@ class Framework: from system.setup import P SystemInstance = P try: - self.db.create_all() + with self.app.app_context(): + self.db.create_all() except Exception as e: self.logger.error('CRITICAL db.create_all()!!!') self.logger.error(f'Exception:{str(e)}') @@ -200,7 +224,6 @@ class Framework: self.logger.info(f"### PORT: {self.config.get('port')}") self.logger.info('### Now you can access App by webbrowser!!') - def __prepare_starting(self): # 여기서 monkey.patch시 너무 늦다고 문제 발생 pass @@ -233,10 +256,6 @@ class Framework: self.config['notify_yaml_filepath'] = os.path.join(self.config['path_data'], 'db', 'notify.yaml') elif mode == "flask": self.app.secret_key = os.urandom(24) - #db_path = os.path.join(self.config['path_data'], 'db', 'system.db') - #self.app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{db_path}check_same_thread=False' - self.app.config['SQLALCHEMY_BINDS'] = {} - self.app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False self.app.config['TEMPLATES_AUTO_RELOAD'] = True self.app.config['JSON_AS_ASCII'] = False elif mode == 'system_loading_after': @@ -327,7 +346,8 @@ class Framework: self.config['plugin_loading_list'] = [] if self.config.get('plugin_except_list') == None: self.config['plugin_except_list'] = [] - + if self.config.get('path_plugins_dev') == None: + self.config['path_plugins_dev'] = None def __make_default_dir(self): diff --git a/lib/framework/init_plugin.py b/lib/framework/init_plugin.py index 863276e..b9a7251 100644 --- a/lib/framework/init_plugin.py +++ b/lib/framework/init_plugin.py @@ -213,9 +213,11 @@ class PluginManager: # import가 끝나면 DB를 만든다. # 플러그인 로드시 DB 초기화를 할 수 있다. + if not F.config['run_celery']: - try: - F.db.create_all() + try: + with F.app.app_context(): + F.db.create_all() except Exception as exception: F.logger.error('Exception:%s', exception) F.logger.error(traceback.format_exc()) diff --git a/lib/framework/templates/base.html b/lib/framework/templates/base.html index f8e22dd..b8f203f 100644 --- a/lib/framework/templates/base.html +++ b/lib/framework/templates/base.html @@ -29,7 +29,8 @@ - + + diff --git a/lib/plugin/logic.py b/lib/plugin/logic.py index 17ccfcc..c626dfb 100644 --- a/lib/plugin/logic.py +++ b/lib/plugin/logic.py @@ -47,21 +47,20 @@ class Logic(object): return for key, value in Logic.db_default.items(): - if F.db.session.query(self.P.ModelSetting).filter_by(key=key).count() == 0: - F.db.session.add(self.P.ModelSetting(key, value)) + if self.P.ModelSetting.get(key) == None: + self.P.ModelSetting.set(key, value) for module in self.P.module_list: if module.page_list is not None: for page_instance in module.page_list: if page_instance.db_default is not None: for key, value in page_instance.db_default.items(): - if F.db.session.query(self.P.ModelSetting).filter_by(key=key).count() == 0: - F.db.session.add(self.P.ModelSetting(key, value)) + if self.P.ModelSetting.get(key) == None: + self.P.ModelSetting.set(key, value) if module.db_default is not None: for key, value in module.db_default.items(): - if F.db.session.query(self.P.ModelSetting).filter_by(key=key).count() == 0: - F.db.session.add(self.P.ModelSetting(key, value)) - F.db.session.commit() + if self.P.ModelSetting.get(key) == None: + self.P.ModelSetting.set(key, value) except Exception as e: self.P.logger.error(f'Exception:{str(e)}') self.P.logger.error(traceback.format_exc()) diff --git a/lib/plugin/model_setting.py b/lib/plugin/model_setting.py index e72aca5..d21e8af 100644 --- a/lib/plugin/model_setting.py +++ b/lib/plugin/model_setting.py @@ -4,7 +4,7 @@ from framework import F def get_model_setting(package_name, logger, table_name=None): - + class ModelSetting(F.db.Model): __tablename__ = '%s_setting' % package_name if table_name is None else table_name __table_args__ = {'mysql_collate': 'utf8_general_ci'} @@ -27,17 +27,19 @@ def get_model_setting(package_name, logger, table_name=None): @staticmethod def get(key): try: - ret = F.db.session.query(ModelSetting).filter_by(key=key).first() - if ret is not None: - return ret.value.strip() - return None + with F.app.app_context(): + ret = F.db.session.query(ModelSetting).filter_by(key=key).first() + if ret is not None: + return ret.value.strip() + return None except Exception as exception: logger.error('Exception:%s %s', exception, key) logger.error(traceback.format_exc()) @staticmethod def has_key(key): - return (F.db.session.query(ModelSetting).filter_by(key=key).first() is not None) + with F.app.app_context(): + return (F.db.session.query(ModelSetting).filter_by(key=key).first() is not None) @staticmethod def get_int(key): @@ -58,13 +60,14 @@ def get_model_setting(package_name, logger, table_name=None): @staticmethod def set(key, value): try: - item = F.db.session.query(ModelSetting).filter_by(key=key).with_for_update().first() - if item is not None: - item.value = value.strip() if value is not None else value - F.db.session.commit() - else: - F.db.session.add(ModelSetting(key, value.strip())) - F.db.session.commit() + with F.app.app_context(): + item = F.db.session.query(ModelSetting).filter_by(key=key).with_for_update().first() + if item is not None: + item.value = value.strip() if value is not None else value + F.db.session.commit() + else: + F.db.session.add(ModelSetting(key, value.strip())) + F.db.session.commit() except Exception as exception: logger.error('Exception:%s %s', exception, key) logger.error(traceback.format_exc())