2
0
mirror of https://github.com/inventree/InvenTree.git synced 2026-05-09 03:03:41 +00:00

!refactor(backend): remove backwards-compatible urls (#11667)

* !refactor(backend): remove backwards-compatible urls

* add changelog entry

* remove mention of CUI

* remove now unneeded test

* fix link
This commit is contained in:
Matthias Mair
2026-04-05 01:28:14 +02:00
committed by GitHub
parent e5def31ec5
commit f631eeb245
8 changed files with 4 additions and 161 deletions
+1
View File
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [#11111](https://github.com/inventree/InvenTree/pull/11111) - removes legacy metadata APIs - [#11111](https://github.com/inventree/InvenTree/pull/11111) - removes legacy metadata APIs
- [#9814](https://github.com/inventree/InvenTree/pull/9814) - removes legacy config path support - [#9814](https://github.com/inventree/InvenTree/pull/9814) - removes legacy config path support
- [#11667](https://github.com/inventree/InvenTree/pull/11667) - removes legacy url patterns
## Unreleased - YYYY-MM-DD ## Unreleased - YYYY-MM-DD
-1
View File
@@ -514,7 +514,6 @@ Set the `INVENTREE_FRONTEND_SETTINGS` Environment variable to a JSON object or u
| `debug` | Set the debug mode | *Server debug mode* | | `debug` | Set the debug mode | *Server debug mode* |
| `environment` | `development` or `production` | *development if Server is in debug mode* | | `environment` | `development` or `production` | *development if Server is in debug mode* |
| `show_server_selector` | In debug mode, show server selector by default. If no servers are specified, show server selector. | | | `show_server_selector` | In debug mode, show server selector by default. If no servers are specified, show server selector. | |
| `url_compatibility` | Support compatibility with "legacy" URLs? | `true` |
| `sentry_dsn` | Set a Sentry DSN url | *Not specified* | | `sentry_dsn` | Set a Sentry DSN url | *Not specified* |
| `mobile_mode` | Controls if InvenTree web UI can be used by mobile devices. There are 3 options: `default` - does not allow mobile devices; `allow-ignore` - shows a mobile device detected banner with a button to ignore this warning AT THE USERS OWN RISK; `allow-always` - skips the mobile check and allows mobile devices always (of course at the server admins OWN RISK) | `default` | | `mobile_mode` | Controls if InvenTree web UI can be used by mobile devices. There are 3 options: `default` - does not allow mobile devices; `allow-ignore` - shows a mobile device detected banner with a button to ignore this warning AT THE USERS OWN RISK; `allow-always` - skips the mobile check and allows mobile devices always (of course at the server admins OWN RISK) | `default` |
+1 -1
View File
@@ -122,7 +122,7 @@ InvenTree uses the [Redis](https://redis.io/) cache server to manage cache data.
!!! info "Redis on Docker" !!! info "Redis on Docker"
Docker adds an additional network layer - that might lead to lower performance than bare metal. Docker adds an additional network layer - that might lead to lower performance than bare metal.
To optimize and configure your redis deployment follow the [official docker guide](https://redis.io/docs/getting-started/install-stack/docker/#configuration). To optimize and configure your redis deployment follow the [official docker guide](https://redis.io/docs/latest/operate/oss_and_stack/install/install-stack/docker/).
!!! tip "Enable Cache" !!! tip "Enable Cache"
While a redis container is provided in the default configuration, by default it is not enabled in the InvenTree server. You can enable redis cache support by following the [caching configuration guide](./config.md#caching) While a redis container is provided in the default configuration, by default it is not enabled in the InvenTree server. You can enable redis cache support by following the [caching configuration guide](./config.md#caching)
+1 -1
View File
@@ -54,7 +54,7 @@ A stock location represents a physical real-world location where *Stock Items* a
### Icons ### Icons
Stock locations can be assigned custom icons (either directly or through [Stock Location Types](#stock-location-type)). In the web interface there is a custom icon picker component available that can help to select the right icon. However in CUI the icon needs to be entered manually. Stock locations can be assigned custom icons (either directly or through [Stock Location Types](#stock-location-type)). In the web interface there is a custom icon picker component available that can help to select the right icon.
By default, the tabler icons package (with prefix: `ti`) is available. To manually select an item, search on the [tabler icons](https://tabler.io/icons) page for an icon and copy its name e.g. `bookmark`. Some icons have a filled and an outline version (if no variants are specified, it's an outline variant). Now these values can be put into the format: `<package-prefix>:<icon-name>:<variant>`. E.g. `ti:bookmark:outline` or `ti:bookmark:filled`. By default, the tabler icons package (with prefix: `ti`) is available. To manually select an item, search on the [tabler icons](https://tabler.io/icons) page for an icon and copy its name e.g. `bookmark`. Some icons have a filled and an outline version (if no variants are specified, it's an outline variant). Now these values can be put into the format: `<package-prefix>:<icon-name>:<variant>`. E.g. `ti:bookmark:outline` or `ti:bookmark:filled`.
@@ -565,15 +565,6 @@ def get_frontend_settings(debug=True):
# If no servers are specified, show server selector # If no servers are specified, show server selector
frontend_settings['show_server_selector'] = True frontend_settings['show_server_selector'] = True
# Support compatibility with "legacy" URLs?
try:
frontend_settings['url_compatibility'] = bool(
frontend_settings.get('url_compatibility', True)
)
except Exception:
# If the value is not a boolean, set it to True
frontend_settings['url_compatibility'] = True
return frontend_settings return frontend_settings
-22
View File
@@ -1789,25 +1789,3 @@ class SchemaPostprocessingTest(TestCase):
self.assertNotIn('customer_detail', schemas_out.get('SalesOrder')['required']) self.assertNotIn('customer_detail', schemas_out.get('SalesOrder')['required'])
# required key removed when empty # required key removed when empty
self.assertNotIn('required', schemas_out.get('SalesOrderShipment')) self.assertNotIn('required', schemas_out.get('SalesOrderShipment'))
class URLCompatibilityTest(InvenTreeTestCase):
"""Unit test for legacy URL compatibility."""
URL_MAPPINGS = [
('/index/', '/web'),
('/part/1/', '/web/part/1/'),
('/company/customers/', '/web/sales/index/customers'),
('/build/3/', '/web/manufacturing/build-order/3'),
('/stock/item/1/', '/web/stock/item/1/'),
]
@override_settings(
SITE_URL='http://testserver', CSRF_TRUSTED_ORIGINS=['http://testserver']
)
def test_legacy_urls(self):
"""Test legacy URLs."""
for old_url, new_url in self.URL_MAPPINGS:
response = self.client.get(old_url)
self.assertEqual(response.status_code, 302)
self.assertEqual(response['Location'], new_url)
-5
View File
@@ -28,7 +28,6 @@ import report.api
import stock.api import stock.api
import users.api import users.api
from plugin.urls import get_plugin_urls from plugin.urls import get_plugin_urls
from web.urls import cui_compatibility_urls
from web.urls import urlpatterns as platform_urls from web.urls import urlpatterns as platform_urls
from .api import ( from .api import (
@@ -182,10 +181,6 @@ urlpatterns.append(
) )
) )
# Compatibility layer for old (CUI) URLs
if settings.FRONTEND_SETTINGS.get('url_compatibility'):
urlpatterns += cui_compatibility_urls(settings.FRONTEND_URL_BASE)
if settings.DJANGO_SILK_ENABLED: if settings.DJANGO_SILK_ENABLED:
urlpatterns += [path('silk/', include('silk.urls', namespace='silk'))] urlpatterns += [path('silk/', include('silk.urls', namespace='silk'))]
+1 -122
View File
@@ -3,131 +3,10 @@
from django.conf import settings from django.conf import settings
from django.urls import include, path, re_path from django.urls import include, path, re_path
from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.csrf import ensure_csrf_cookie
from django.views.generic import RedirectView, TemplateView from django.views.generic import TemplateView
spa_view = ensure_csrf_cookie(TemplateView.as_view(template_name='web/index.html')) spa_view = ensure_csrf_cookie(TemplateView.as_view(template_name='web/index.html'))
def cui_compatibility_urls(base: str) -> list:
"""Generate a list of URL patterns for compatibility with old (CUI) URLs.
These URLs are provided for backwards compatibility with older versions of InvenTree,
before we moved to a SPA (Single Page Application) architecture in the 1.0.0 release.
At some future point these may be removed?
Args:
base (str): The base URL to use for generating the patterns.
Returns:
list: A list of URL patterns.
"""
return [
# Old 'index' view - reroute to the dashboard
path('index/', RedirectView.as_view(url=f'/{base}')),
path('settings/', RedirectView.as_view(url=f'/{base}/settings')),
# Company patterns
path(
'company/',
include([
path(
'customers/',
RedirectView.as_view(url=f'/{base}/sales/index/customers'),
),
path(
'manufacturers/',
RedirectView.as_view(url=f'/{base}/purchasing/index/manufacturers'),
),
path(
'suppliers/',
RedirectView.as_view(url=f'/{base}/purchasing/index/suppliers'),
),
re_path(
r'(?P<pk>\d+)/', RedirectView.as_view(url=f'/{base}/company/%(pk)s')
),
]),
),
# "Part" app views
re_path(
r'^part/(?P<path>.*)$', RedirectView.as_view(url=f'/{base}/part/%(path)s')
),
# "Stock" app views
re_path(
r'^stock/(?P<path>.*)$', RedirectView.as_view(url=f'/{base}/stock/%(path)s')
),
# "Build" app views (requires some custom handling)
path(
'build/',
include([
re_path(
r'^(?P<pk>\d+)/',
RedirectView.as_view(
url=f'/{base}/manufacturing/build-order/%(pk)s'
),
),
re_path('.*', RedirectView.as_view(url=f'/{base}/manufacturing/')),
]),
),
# "Order" app views
path(
'order/',
include([
path(
'purchase-order/',
include([
re_path(
r'^(?P<pk>\d+)/',
RedirectView.as_view(
url=f'/{base}/purchasing/purchase-order/%(pk)s'
),
),
re_path(
'.*',
RedirectView.as_view(
url=f'/{base}/purchasing/index/purchaseorders/'
),
),
]),
),
path(
'sales-order/',
include([
re_path(
r'^(?P<pk>\d+)/',
RedirectView.as_view(
url=f'/{base}/sales/sales-order/%(pk)s'
),
),
re_path(
'.*',
RedirectView.as_view(
url=f'/{base}/sales/index/salesorders/'
),
),
]),
),
path(
'return-order/',
include([
re_path(
r'^(?P<pk>\d+)/',
RedirectView.as_view(
url=f'/{base}/sales/return-order/%(pk)s'
),
),
re_path(
'.*',
RedirectView.as_view(
url=f'/{base}/sales/index/returnorders/'
),
),
]),
),
]),
),
]
urlpatterns = [ urlpatterns = [
path( path(
f'{settings.FRONTEND_URL_BASE}/', f'{settings.FRONTEND_URL_BASE}/',