mirror of
https://github.com/django-components/django-components.git
synced 2025-11-13 20:25:20 +00:00
refactor: do not call URLResolver._populate() if not needed
This commit is contained in:
parent
39e4d78dc5
commit
77df93b5b1
6 changed files with 38 additions and 11 deletions
|
|
@ -1,5 +1,11 @@
|
||||||
# Release notes
|
# Release notes
|
||||||
|
|
||||||
|
## v0.143.1
|
||||||
|
|
||||||
|
#### Fix
|
||||||
|
|
||||||
|
- Make django-component's position in Django's `INSTALLED_APPS` more lenient by not calling Django's `URLResolver._populate()` if `URLResolver` hasn't been resolved before ([See thread](https://discord.com/channels/1417824875023700000/1417825089675853906/1437034834118840411)).
|
||||||
|
|
||||||
## v0.143.0
|
## v0.143.0
|
||||||
|
|
||||||
#### Feat
|
#### Feat
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "django_components"
|
name = "django_components"
|
||||||
version = "0.143.0"
|
version = "0.143.1"
|
||||||
requires-python = ">=3.8, <4.0"
|
requires-python = ">=3.8, <4.0"
|
||||||
description = "A way to create simple reusable template components in Django."
|
description = "A way to create simple reusable template components in Django."
|
||||||
keywords = ["django", "components", "css", "js", "html"]
|
keywords = ["django", "components", "css", "js", "html"]
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,6 @@ asv==0.6.5
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
asv-runner==0.2.1
|
asv-runner==0.2.1
|
||||||
# via asv
|
# via asv
|
||||||
backports-asyncio-runner==1.2.0
|
|
||||||
# via pytest-asyncio
|
|
||||||
build==1.3.0
|
build==1.3.0
|
||||||
# via asv
|
# via asv
|
||||||
cachetools==6.2.0
|
cachetools==6.2.0
|
||||||
|
|
|
||||||
|
|
@ -1163,9 +1163,7 @@ class ExtensionManager:
|
||||||
extensions_url_resolver.url_patterns = urls
|
extensions_url_resolver.url_patterns = urls
|
||||||
|
|
||||||
# Rebuild URL resolver cache to be able to resolve the new routes by their names.
|
# Rebuild URL resolver cache to be able to resolve the new routes by their names.
|
||||||
urlconf = get_urlconf()
|
self._lazy_populate_resolver()
|
||||||
resolver = get_resolver(urlconf)
|
|
||||||
resolver._populate()
|
|
||||||
|
|
||||||
# Flush stored events
|
# Flush stored events
|
||||||
#
|
#
|
||||||
|
|
@ -1190,6 +1188,22 @@ class ExtensionManager:
|
||||||
getattr(self, hook)(data)
|
getattr(self, hook)(data)
|
||||||
self._events = []
|
self._events = []
|
||||||
|
|
||||||
|
# Django processes the paths from `urlpatterns` only once.
|
||||||
|
# This is at conflict with how we handle URL paths introduced by extensions,
|
||||||
|
# which may happen AFTER Django processes `urlpatterns`.
|
||||||
|
# If that happens, we need to force Django to re-process `urlpatterns`.
|
||||||
|
# If we don't do it, then the new paths added by our extensions won't work
|
||||||
|
# with e.g. `django.url.reverse()`.
|
||||||
|
# See https://discord.com/channels/1417824875023700000/1417825089675853906/1437034834118840411
|
||||||
|
def _lazy_populate_resolver(self) -> None:
|
||||||
|
urlconf = get_urlconf()
|
||||||
|
root_resolver = get_resolver(urlconf)
|
||||||
|
# However, if Django has NOT yet processed the `urlpatterns`, then do nothing.
|
||||||
|
# If we called `_populate()` in such case, we may break people's projects
|
||||||
|
# as the values may be resolved prematurely, before all the needed code is loaded.
|
||||||
|
if root_resolver._populated:
|
||||||
|
root_resolver._populate()
|
||||||
|
|
||||||
def get_extension(self, name: str) -> ComponentExtension:
|
def get_extension(self, name: str) -> ComponentExtension:
|
||||||
for extension in self.extensions:
|
for extension in self.extensions:
|
||||||
if extension.name == name:
|
if extension.name == name:
|
||||||
|
|
@ -1221,12 +1235,8 @@ class ExtensionManager:
|
||||||
all_urls.append(urlpattern)
|
all_urls.append(urlpattern)
|
||||||
did_add_urls = True
|
did_add_urls = True
|
||||||
|
|
||||||
# Force Django's URLResolver to update its lookups, so things like `reverse()` work
|
|
||||||
if did_add_urls:
|
if did_add_urls:
|
||||||
# Django's root URLResolver
|
self._lazy_populate_resolver()
|
||||||
urlconf = get_urlconf()
|
|
||||||
root_resolver = get_resolver(urlconf)
|
|
||||||
root_resolver._populate()
|
|
||||||
|
|
||||||
def remove_extension_urls(self, name: str, urls: List[URLRoute]) -> None:
|
def remove_extension_urls(self, name: str, urls: List[URLRoute]) -> None:
|
||||||
if not self._initialized:
|
if not self._initialized:
|
||||||
|
|
|
||||||
|
|
@ -585,5 +585,11 @@ def _clear_djc_global_state(
|
||||||
if gc_collect:
|
if gc_collect:
|
||||||
gc.collect()
|
gc.collect()
|
||||||
|
|
||||||
|
# Clear Django's URL resolver cache, so that any URLs that were added
|
||||||
|
# during tests are removed.
|
||||||
|
from django.urls.resolvers import _get_cached_resolver # noqa: PLC0415
|
||||||
|
|
||||||
|
_get_cached_resolver.cache_clear()
|
||||||
|
|
||||||
global IS_TESTING # noqa: PLW0603
|
global IS_TESTING # noqa: PLW0603
|
||||||
IS_TESTING = False
|
IS_TESTING = False
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import pytest
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.template import Context, Origin, Template
|
from django.template import Context, Origin, Template
|
||||||
from django.test import Client
|
from django.test import Client
|
||||||
|
from django.urls import get_resolver, get_urlconf
|
||||||
|
|
||||||
from django_components import Component, Slot, SlotNode, register, registry
|
from django_components import Component, Slot, SlotNode, register, registry
|
||||||
from django_components.app_settings import app_settings
|
from django_components.app_settings import app_settings
|
||||||
|
|
@ -649,6 +650,12 @@ class TestExtensionHooks:
|
||||||
|
|
||||||
@djc_test
|
@djc_test
|
||||||
class TestExtensionViews:
|
class TestExtensionViews:
|
||||||
|
@djc_test(components_settings={"extensions": [DummyExtension]})
|
||||||
|
def test_resolver_not_populated_needlessly(self):
|
||||||
|
urlconf = get_urlconf()
|
||||||
|
resolver = get_resolver(urlconf)
|
||||||
|
assert not resolver._populated
|
||||||
|
|
||||||
@djc_test(components_settings={"extensions": [DummyExtension]})
|
@djc_test(components_settings={"extensions": [DummyExtension]})
|
||||||
def test_views(self):
|
def test_views(self):
|
||||||
client = Client()
|
client = Client()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue