mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-28 19:46:46 +00:00
Plugin loading fixes (#5572)
* Add config function to return external plugins dir * Enable AppMixin support relative to external plugins directory * Fix for urls.py - URL patterns were causing custom app mixin plugins to fail reverse lookup in admin interface - Brought admin URLs up one level * simplify urls.py * Fix plugin registry code which registers plugin URLs - As we have updated InvenTree.urls.py we need to adjust this logic too * Adds redirect for favicon.ico * Handle empty plugins dir
This commit is contained in:
parent
cf4df3402c
commit
47f341d2b5
@ -281,6 +281,12 @@ def get_plugin_file():
|
|||||||
return plugin_file
|
return plugin_file
|
||||||
|
|
||||||
|
|
||||||
|
def get_plugin_dir():
|
||||||
|
"""Returns the path of the custom plugins directory"""
|
||||||
|
|
||||||
|
return get_setting('INVENTREE_PLUGIN_DIR', 'plugin_dir')
|
||||||
|
|
||||||
|
|
||||||
def get_secret_key():
|
def get_secret_key():
|
||||||
"""Return the secret key value which will be used by django.
|
"""Return the secret key value which will be used by django.
|
||||||
|
|
||||||
|
@ -189,10 +189,6 @@ classic_frontendpatterns = [
|
|||||||
re_path(r'^about/', AboutView.as_view(), name='about'),
|
re_path(r'^about/', AboutView.as_view(), name='about'),
|
||||||
re_path(r'^stats/', DatabaseStatsView.as_view(), name='stats'),
|
re_path(r'^stats/', DatabaseStatsView.as_view(), name='stats'),
|
||||||
|
|
||||||
# admin sites
|
|
||||||
re_path(f'^{settings.INVENTREE_ADMIN_URL}/error_log/', include('error_report.urls')),
|
|
||||||
re_path(f'^{settings.INVENTREE_ADMIN_URL}/', admin.site.urls, name='inventree-admin'),
|
|
||||||
|
|
||||||
# DB user sessions
|
# DB user sessions
|
||||||
path('accounts/sessions/other/delete/', view=CustomSessionDeleteOtherView.as_view(), name='session_delete_other', ),
|
path('accounts/sessions/other/delete/', view=CustomSessionDeleteOtherView.as_view(), name='session_delete_other', ),
|
||||||
re_path(r'^accounts/sessions/(?P<pk>\w+)/delete/$', view=CustomSessionDeleteView.as_view(), name='session_delete', ),
|
re_path(r'^accounts/sessions/(?P<pk>\w+)/delete/$', view=CustomSessionDeleteView.as_view(), name='session_delete', ),
|
||||||
@ -213,22 +209,26 @@ classic_frontendpatterns = [
|
|||||||
|
|
||||||
new_frontendpatterns = platform_urls
|
new_frontendpatterns = platform_urls
|
||||||
|
|
||||||
# Load patterns for frontend according to settings
|
urlpatterns = [
|
||||||
frontendpatterns = []
|
# admin sites
|
||||||
if settings.ENABLE_CLASSIC_FRONTEND:
|
re_path(f'^{settings.INVENTREE_ADMIN_URL}/error_log/', include('error_report.urls')),
|
||||||
frontendpatterns.append(re_path('', include(classic_frontendpatterns)))
|
re_path(f'^{settings.INVENTREE_ADMIN_URL}/', admin.site.urls, name='inventree-admin'),
|
||||||
if settings.ENABLE_PLATFORM_FRONTEND:
|
]
|
||||||
frontendpatterns.append(re_path('', include(new_frontendpatterns)))
|
|
||||||
|
|
||||||
|
urlpatterns += backendpatterns
|
||||||
|
|
||||||
|
frontendpatterns = []
|
||||||
|
|
||||||
|
if settings.ENABLE_CLASSIC_FRONTEND:
|
||||||
|
frontendpatterns += classic_frontendpatterns
|
||||||
|
if settings.ENABLE_PLATFORM_FRONTEND:
|
||||||
|
frontendpatterns += new_frontendpatterns
|
||||||
|
|
||||||
|
urlpatterns += frontendpatterns
|
||||||
|
|
||||||
# Append custom plugin URLs (if plugin support is enabled)
|
# Append custom plugin URLs (if plugin support is enabled)
|
||||||
if settings.PLUGINS_ENABLED:
|
if settings.PLUGINS_ENABLED:
|
||||||
frontendpatterns.append(get_plugin_urls())
|
urlpatterns.append(get_plugin_urls())
|
||||||
|
|
||||||
urlpatterns = [
|
|
||||||
re_path('', include(frontendpatterns)),
|
|
||||||
re_path('', include(backendpatterns)),
|
|
||||||
]
|
|
||||||
|
|
||||||
# Server running in "DEBUG" mode?
|
# Server running in "DEBUG" mode?
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
@ -245,5 +245,10 @@ if settings.DEBUG:
|
|||||||
path('__debug__/', include(debug_toolbar.urls)),
|
path('__debug__/', include(debug_toolbar.urls)),
|
||||||
] + urlpatterns
|
] + urlpatterns
|
||||||
|
|
||||||
|
# Redirect for favicon.ico
|
||||||
|
urlpatterns.append(
|
||||||
|
path('favicon.ico', RedirectView.as_view(url=f'{settings.STATIC_ROOT}/img/favicon/favicon.ico'))
|
||||||
|
)
|
||||||
|
|
||||||
# Send any unknown URLs to the parts page
|
# Send any unknown URLs to the parts page
|
||||||
urlpatterns += [re_path(r'^.*$', RedirectView.as_view(url='/index/', permanent=False), name='index')]
|
urlpatterns += [re_path(r'^.*$', RedirectView.as_view(url='/index/', permanent=False), name='index')]
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
"""Plugin mixin class for AppMixin."""
|
"""Plugin mixin class for AppMixin."""
|
||||||
import logging
|
import logging
|
||||||
from importlib import reload
|
from importlib import reload
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
|
from InvenTree.config import get_plugin_dir
|
||||||
|
|
||||||
logger = logging.getLogger('inventree')
|
logger = logging.getLogger('inventree')
|
||||||
|
|
||||||
|
|
||||||
@ -156,12 +159,22 @@ class AppMixin:
|
|||||||
- a local file / dir
|
- a local file / dir
|
||||||
- a package
|
- a package
|
||||||
"""
|
"""
|
||||||
try:
|
path = plugin.path()
|
||||||
# for local path plugins
|
custom_plugins_dir = get_plugin_dir()
|
||||||
plugin_path = '.'.join(plugin.path().relative_to(settings.BASE_DIR).parts)
|
|
||||||
except ValueError: # pragma: no cover
|
if path.is_relative_to(settings.BASE_DIR):
|
||||||
|
# Plugins which are located relative to the base code directory
|
||||||
|
plugin_path = '.'.join(path.relative_to(settings.BASE_DIR).parts)
|
||||||
|
elif custom_plugins_dir and path.is_relative_to(custom_plugins_dir):
|
||||||
|
# Plugins which are located relative to the custom plugins directory
|
||||||
|
plugin_path = '.'.join(path.relative_to(custom_plugins_dir).parts)
|
||||||
|
|
||||||
|
# Ensure that the parent directory is added also
|
||||||
|
plugin_path = Path(custom_plugins_dir).parts[-1] + '.' + plugin_path
|
||||||
|
else:
|
||||||
# plugin is shipped as package - extract plugin module name
|
# plugin is shipped as package - extract plugin module name
|
||||||
plugin_path = plugin.__module__.split('.')[0]
|
plugin_path = plugin.__module__.split('.')[0]
|
||||||
|
|
||||||
return plugin_path
|
return plugin_path
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
@ -17,14 +17,14 @@ from django.apps import apps
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.db.utils import IntegrityError, OperationalError, ProgrammingError
|
from django.db.utils import IntegrityError, OperationalError, ProgrammingError
|
||||||
from django.urls import clear_url_caches, include, re_path
|
from django.urls import clear_url_caches, re_path
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from maintenance_mode.core import (get_maintenance_mode, maintenance_mode_on,
|
from maintenance_mode.core import (get_maintenance_mode, maintenance_mode_on,
|
||||||
set_maintenance_mode)
|
set_maintenance_mode)
|
||||||
|
|
||||||
from InvenTree.config import get_setting
|
from InvenTree.config import get_plugin_dir
|
||||||
from InvenTree.ready import canAppAccessDatabase
|
from InvenTree.ready import canAppAccessDatabase
|
||||||
|
|
||||||
from .helpers import (IntegrationPluginError, get_entrypoints, get_plugins,
|
from .helpers import (IntegrationPluginError, get_entrypoints, get_plugins,
|
||||||
@ -239,7 +239,7 @@ class PluginsRegistry:
|
|||||||
if settings.TESTING:
|
if settings.TESTING:
|
||||||
custom_dirs = os.getenv('INVENTREE_PLUGIN_TEST_DIR', None)
|
custom_dirs = os.getenv('INVENTREE_PLUGIN_TEST_DIR', None)
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
custom_dirs = get_setting('INVENTREE_PLUGIN_DIR', 'plugin_dir')
|
custom_dirs = get_plugin_dir()
|
||||||
|
|
||||||
# Load from user specified directories (unless in testing mode)
|
# Load from user specified directories (unless in testing mode)
|
||||||
dirs.append('plugins')
|
dirs.append('plugins')
|
||||||
@ -577,19 +577,28 @@ class PluginsRegistry:
|
|||||||
self.plugins_full: Dict[str, InvenTreePlugin] = {}
|
self.plugins_full: Dict[str, InvenTreePlugin] = {}
|
||||||
|
|
||||||
def _update_urls(self):
|
def _update_urls(self):
|
||||||
from InvenTree.urls import frontendpatterns as urlpattern
|
"""Due to the order in which plugins are loaded, the patterns in urls.py may be out of date.
|
||||||
from InvenTree.urls import urlpatterns as global_pattern
|
|
||||||
|
This function updates the patterns in urls.py to ensure that the correct patterns are loaded,
|
||||||
|
and then refreshes the django url cache.
|
||||||
|
|
||||||
|
Note that we also have to refresh the admin site URLS,
|
||||||
|
as any custom AppMixin plugins require admin integration
|
||||||
|
"""
|
||||||
|
|
||||||
|
from InvenTree.urls import urlpatterns
|
||||||
from plugin.urls import get_plugin_urls
|
from plugin.urls import get_plugin_urls
|
||||||
|
|
||||||
for index, url in enumerate(urlpattern):
|
for index, url in enumerate(urlpatterns):
|
||||||
if hasattr(url, 'app_name'):
|
|
||||||
if url.app_name == 'admin':
|
|
||||||
urlpattern[index] = re_path(r'^admin/', admin.site.urls, name='inventree-admin')
|
|
||||||
elif url.app_name == 'plugin':
|
|
||||||
urlpattern[index] = get_plugin_urls()
|
|
||||||
|
|
||||||
# Replace frontendpatterns
|
app_name = getattr(url, 'app_name', None)
|
||||||
global_pattern[0] = re_path('', include(urlpattern))
|
|
||||||
|
if app_name == 'admin':
|
||||||
|
urlpatterns[index] = re_path(r'^admin/', admin.site.urls, name='inventree-admin')
|
||||||
|
if app_name == 'plugin':
|
||||||
|
urlpatterns[index] = get_plugin_urls()
|
||||||
|
|
||||||
|
# Refresh the URL cache
|
||||||
clear_url_caches()
|
clear_url_caches()
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user