From 2552d27f6fc440fdb538ccee4209dceb215ef2c6 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 6 Apr 2023 17:22:02 +0200 Subject: [PATCH] added plugin architecture --- .gitignore | 1 + .idea/recipes.iml | 2 +- recipes/settings.py | 43 ++++++++++++++++++++++++++++++++++++++++++- recipes/urls.py | 14 ++++++++++++++ 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index b0d71b26..ad9c1fc7 100644 --- a/.gitignore +++ b/.gitignore @@ -78,6 +78,7 @@ postgresql/ /docker-compose.override.yml vue/node_modules +plugins .vscode/ vetur.config.js cookbook/static/vue diff --git a/.idea/recipes.iml b/.idea/recipes.iml index 1b96c9d8..8a0e59c8 100644 --- a/.idea/recipes.iml +++ b/.idea/recipes.iml @@ -18,7 +18,7 @@ - + diff --git a/recipes/settings.py b/recipes/settings.py index 3dd93bf2..8fed7258 100644 --- a/recipes/settings.py +++ b/recipes/settings.py @@ -13,6 +13,8 @@ import ast import json import os import re +import sys +import traceback from django.contrib import messages from django.utils.translation import gettext_lazy as _ @@ -117,6 +119,34 @@ INSTALLED_APPS = [ 'treebeard', ] +PLUGINS = [] +try: + for d in os.listdir(os.path.join(BASE_DIR, 'recipes', 'plugins')): + if d != '__pycache__': + try: + apps_path = f'recipes.plugins.{d}.apps' + __import__(apps_path) + app_config_classname = dir(sys.modules[apps_path])[1] + plugin_module = f'recipes.plugins.{d}.apps.{app_config_classname}' + if plugin_module not in INSTALLED_APPS: + INSTALLED_APPS.append(plugin_module) + plugin_class = getattr(sys.modules[apps_path], app_config_classname) + plugin_config = { + 'name': plugin_class.verbose_name if hasattr(plugin_class, 'verbose_name') else plugin_class.name, + 'module': f'recipes.plugins.{d}', + 'base_path': os.path.join(BASE_DIR, 'recipes', 'plugins', d), + 'base_url': plugin_class.base_url, + 'bundle_name': plugin_class.bundle_name if hasattr(plugin_class, 'bundle_name') else '', + } + PLUGINS.append(plugin_config) + except Exception: + if DEBUG: + traceback.print_exc() + print(f'ERROR failed to initialize plugin {d}') +except Exception: + if DEBUG: + print('ERROR failed to initialize plugins') + SOCIAL_PROVIDERS = os.getenv('SOCIAL_PROVIDERS').split(',') if os.getenv('SOCIAL_PROVIDERS') else [] SOCIALACCOUNT_EMAIL_VERIFICATION = 'none' INSTALLED_APPS = INSTALLED_APPS + SOCIAL_PROVIDERS @@ -362,9 +392,20 @@ WEBPACK_LOADER = { 'POLL_INTERVAL': 0.1, 'TIMEOUT': None, 'IGNORE': [r'.+\.hot-update.js', r'.+\.map'], - } + }, } +for p in PLUGINS: + if p['bundle_name'] != '': + WEBPACK_LOADER[p['bundle_name']] = { + 'CACHE': not DEBUG, + 'BUNDLE_DIR_NAME': f'{p["base_path"]}/vue/', # must end with slash + 'STATS_FILE': os.path.join(p["base_path"], 'vue', 'webpack-stats.json'), + 'POLL_INTERVAL': 0.1, + 'TIMEOUT': None, + 'IGNORE': [r'.+\.hot-update.js', r'.+\.map'], + } + # Internationalization # https://docs.djangoproject.com/en/2.0/topics/i18n/ diff --git a/recipes/urls.py b/recipes/urls.py index ffe02e90..660cbd2e 100644 --- a/recipes/urls.py +++ b/recipes/urls.py @@ -14,6 +14,8 @@ Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ +import traceback + from django.conf import settings from django.contrib import admin from django.urls import include, path, re_path @@ -42,3 +44,15 @@ if settings.ENABLE_METRICS: if settings.GUNICORN_MEDIA or settings.DEBUG: urlpatterns += re_path(r'^media/(?P.*)$', serve, {'document_root': settings.MEDIA_ROOT}), urlpatterns += re_path(r'^jsreverse.json$', reverse_views.urls_js, name='js_reverse'), + +for p in settings.PLUGINS: + try: + urlpatterns += path(p['base_url'], include(f'{p["module"]}.urls')), + except ModuleNotFoundError as e: + if settings.DEBUG: + print(e.msg) + print(f'ERROR failed loading plugin <{p["name"]}> urls, did you forget creating urls.py in your plugin?') + except Exception as e: + if settings.DEBUG: + print(f'ERROR failed loading urls for plugin <{p["name"]}>') + traceback.format_exc()