Coverage for src/backend/InvenTree/plugin/urls.py: 24%
27 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 17:47 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 17:47 +0000
1"""URL lookup for plugin app."""
3from django.conf import settings
4from django.urls import include, re_path
5from django.urls.exceptions import Resolver404
6from django.views.generic.base import RedirectView
8from common.validators import get_global_setting
9from InvenTree.exceptions import log_error
10from plugin import PluginMixinEnum
12PLUGIN_BASE = 'plugin' # Constant for links
15def get_plugin_urls():
16 """Returns a urlpattern that can be integrated into the global urls."""
17 from plugin.registry import registry
19 urls = []
21 if registry.is_ready:
22 if (
23 get_global_setting('ENABLE_PLUGINS_URL', False)
24 or settings.PLUGIN_TESTING_SETUP
25 ):
26 for plugin in registry.with_mixin(PluginMixinEnum.URLS):
27 try:
28 if plugin_urls := plugin.urlpatterns:
29 # Check if the plugin has a custom URL pattern
30 for url in plugin_urls:
31 # Attempt to resolve against the URL pattern as a validation check
32 try:
33 url.resolve('')
34 except Resolver404:
35 pass
37 urls.append(
38 re_path(
39 f'^{plugin.slug}/',
40 include((plugin_urls, plugin.slug)),
41 name=plugin.slug,
42 )
43 )
44 except Exception:
45 log_error('get_plugin_urls', plugin=plugin.slug)
46 continue
48 # Redirect anything else to the root index
49 urls.append(
50 re_path(
51 r'^.*$',
52 RedirectView.as_view(url=f'/{settings.FRONTEND_URL_BASE}', permanent=False),
53 name='index',
54 )
55 )
57 return re_path(f'^{PLUGIN_BASE}/', include((urls, 'plugin')))