diff --git a/django_utils_lib/lazy.py b/django_utils_lib/lazy.py new file mode 100644 index 0000000..7296e64 --- /dev/null +++ b/django_utils_lib/lazy.py @@ -0,0 +1,21 @@ +class LazyDjango: + """ + Django has a few modules where if you import something from them, + they trigger side-effects that can crash the app if called at import-time + vs run-time. Notably things related to auth that trigger apps / settings + checks. + + This class is a workaround, without using a full app registration system, + to just use lazy-imports. + """ + + @property + def redirect_to_login(self): + if self._redirect_to_login is None: + from django.contrib.auth.views import redirect_to_login + + self._redirect_to_login = redirect_to_login + return self._redirect_to_login + + +lazy_django = LazyDjango() diff --git a/django_utils_lib/requests.py b/django_utils_lib/requests.py index 4e0facf..a3aa551 100644 --- a/django_utils_lib/requests.py +++ b/django_utils_lib/requests.py @@ -3,7 +3,6 @@ import pydantic from django.conf import settings -from django.contrib.auth.views import redirect_to_login from django.http import ( FileResponse, HttpRequest, @@ -15,6 +14,8 @@ from django.urls import re_path from django.views.static import serve +from django_utils_lib.lazy import lazy_django + class SimpleStaticFileServerConfig(pydantic.BaseModel): auth_required_path_patterns: Optional[List[re.Pattern]] = pydantic.Field(default=None) @@ -76,7 +77,7 @@ def guard_path(self, request: HttpRequest, url_path: str) -> Optional[HttpRespon # Check for attempted access to an auth-required path from a non-authed user if self.config.auth_required_path_patterns and not request.user.is_authenticated: if any(pattern.search(url_path) for pattern in self.config.auth_required_path_patterns): - return redirect_to_login(next=request.get_full_path()) + return lazy_django.redirect_to_login(next=request.get_full_path()) # Pass request forward / noop return None diff --git a/django_utils_lib/tests/test_simplestaticfileserver.py b/django_utils_lib/tests/test_simplestaticfileserver.py index 8554bb2..fa05364 100644 --- a/django_utils_lib/tests/test_simplestaticfileserver.py +++ b/django_utils_lib/tests/test_simplestaticfileserver.py @@ -52,7 +52,10 @@ class StaticFileServerTestCase(TypedDict): ), ], ) -@mock.patch("django_utils_lib.requests.redirect_to_login", return_value=HttpResponseRedirect("")) +@mock.patch( + "django_utils_lib.lazy.LazyDjango.redirect_to_login", + new_callable=mock.PropertyMock(return_value=mock.MagicMock(return_value=HttpResponseRedirect(""))), +) @mock.patch("django_utils_lib.requests.serve", return_value=FileResponse()) def test_path_guarding( mock_serve: mock.Mock,