Opened 20 months ago
Last modified 15 months ago
#34451 assigned Bug
Incorrect handling of ImproperlyConfigured Exception in views in ASGI context — at Version 1
Reported by: | Michael Galler | Owned by: | nobody |
---|---|---|---|
Component: | Error reporting | Version: | 4.1 |
Severity: | Normal | Keywords: | |
Cc: | asgi | Triage Stage: | Accepted |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
start with
django-admin startproject myproject
views.py
from django.views.generic import FormView class TestView(FormView): async def post(self, request, *args, **kwargs): return 'Foobar'
urls.py
from django.contrib import admin from django.urls import path from myproject.views import TestView urlpatterns = [ path('admin/', admin.site.urls), path('test/', TestView.as_view()), ]
This should raise
django.core.exceptions.ImproperlyConfigured: TestView HTTP handlers must either be all sync or all async.
Running the devserver via manage.py results in
C:\code\myproject\venv\Scripts\python.exe C:\code\myproject\manage.py runserver 8000 Performing system checks... Watching for file changes with StatReloader Exception in thread django-main-thread: Traceback (most recent call last): File "C:\Program Files\Python311\Lib\threading.py", line 1038, in _bootstrap_inner self.run() File "C:\Program Files\Python311\Lib\threading.py", line 975, in run self._target(*self._args, **self._kwargs) File "C:\code\myproject\venv\Lib\site-packages\django\utils\autoreload.py", line 64, in wrapper fn(*args, **kwargs) File "C:\code\myproject\venv\Lib\site-packages\django\core\management\commands\runserver.py", line 134, in inner_run self.check(display_num_errors=True) File "C:\code\myproject\venv\Lib\site-packages\django\core\management\base.py", line 475, in check all_issues = checks.run_checks( ^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\core\checks\registry.py", line 88, in run_checks new_errors = check(app_configs=app_configs, databases=databases) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\core\checks\urls.py", line 14, in check_url_config return check_resolver(resolver) ^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\core\checks\urls.py", line 24, in check_resolver return check_method() ^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 494, in check for pattern in self.url_patterns: ^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__ res = instance.__dict__[self.name] = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 715, in url_patterns patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module) ^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__ res = instance.__dict__[self.name] = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 708, in urlconf_module return import_module(self.urlconf_name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\Python311\Lib\importlib\__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "<frozen importlib._bootstrap>", line 1206, in _gcd_import File "<frozen importlib._bootstrap>", line 1178, in _find_and_load File "<frozen importlib._bootstrap>", line 1149, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 690, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 940, in exec_module File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed File "C:\code\myproject\myproject\urls.py", line 8, in <module> path('test/', TestView.as_view()), ^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\views\generic\base.py", line 119, in as_view if cls.view_is_async: ^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 71, in __get__ return self.fget(cls) ^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\views\generic\base.py", line 73, in view_is_async raise ImproperlyConfigured( django.core.exceptions.ImproperlyConfigured: TestView HTTP handlers must either be all sync or all async.
Now the same thing with hypercorn will result in some sort of recursion that I do not understand.
Uvicorn behaves the same way.
(venv) λ hypercorn myproject.asgi:application [2023-03-31 11:54:00 +0200] [16000] [WARNING] ASGI Framework Lifespan error, continuing without Lifespan support [2023-03-31 11:54:00 +0200] [16000] [INFO] Running on http://127.0.0.1:8000 (CTRL + C to quit) [2023-03-31 11:54:08 +0200] [16000] [ERROR] Error in ASGI Framework Traceback (most recent call last): File "C:\code\myproject\venv\Lib\site-packages\asgiref\sync.py", line 486, in thread_handler raise exc_info[1] File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\exception.py", line 43, in inner response = await get_response(request) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\base.py", line 235, in _get_response_async callback, callback_args, callback_kwargs = self.resolve_request(request) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\base.py", line 313, in resolve_request resolver_match = resolver.resolve(request.path_info) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 663, in resolve for pattern in self.url_patterns: ^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__ res = instance.__dict__[self.name] = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 715, in url_patterns patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module) ^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__ res = instance.__dict__[self.name] = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 708, in urlconf_module return import_module(self.urlconf_name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\Python311\Lib\importlib\__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "<frozen importlib._bootstrap>", line 1206, in _gcd_import File "<frozen importlib._bootstrap>", line 1178, in _find_and_load File "<frozen importlib._bootstrap>", line 1149, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 690, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 940, in exec_module File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed File "C:\code\myproject\myproject\urls.py", line 8, in <module> path('test/', TestView.as_view()), ^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\views\generic\base.py", line 119, in as_view if cls.view_is_async: ^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 71, in __get__ return self.fget(cls) ^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\views\generic\base.py", line 73, in view_is_async raise ImproperlyConfigured( django.core.exceptions.ImproperlyConfigured: TestView HTTP handlers must either be all sync or all async. During handling of the above exception, another exception occurred: ... (the same frame over and over again)
#############################################################################################
In my personal project this leads to a strange problem with django-ninja
api.py
from ninja import NinjaAPI api = NinjaAPI()
urls.py
from django.contrib import admin from django.urls import path from myproject.api import api from myproject.views import TestView urlpatterns = [ path('admin/', admin.site.urls), path("api/", api.urls), path('test/', TestView.as_view()), ]
manage.py devserver:
C:\code\myproject\venv\Scripts\python.exe C:\code\myproject\manage.py runserver 8000 Watching for file changes with StatReloader Performing system checks... Exception in thread django-main-thread: Traceback (most recent call last): File "C:\Program Files\Python311\Lib\threading.py", line 1038, in _bootstrap_inner self.run() File "C:\Program Files\Python311\Lib\threading.py", line 975, in run self._target(*self._args, **self._kwargs) File "C:\code\myproject\venv\Lib\site-packages\django\utils\autoreload.py", line 64, in wrapper fn(*args, **kwargs) File "C:\code\myproject\venv\Lib\site-packages\django\core\management\commands\runserver.py", line 134, in inner_run self.check(display_num_errors=True) File "C:\code\myproject\venv\Lib\site-packages\django\core\management\base.py", line 475, in check all_issues = checks.run_checks( ^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\core\checks\registry.py", line 88, in run_checks new_errors = check(app_configs=app_configs, databases=databases) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\core\checks\urls.py", line 14, in check_url_config return check_resolver(resolver) ^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\core\checks\urls.py", line 24, in check_resolver return check_method() ^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 494, in check for pattern in self.url_patterns: ^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__ res = instance.__dict__[self.name] = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 715, in url_patterns patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module) ^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__ res = instance.__dict__[self.name] = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 708, in urlconf_module return import_module(self.urlconf_name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\Python311\Lib\importlib\__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "<frozen importlib._bootstrap>", line 1206, in _gcd_import File "<frozen importlib._bootstrap>", line 1178, in _find_and_load File "<frozen importlib._bootstrap>", line 1149, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 690, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 940, in exec_module File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed File "C:\code\myproject\myproject\urls.py", line 10, in <module> path('test/', TestView.as_view()), ^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\views\generic\base.py", line 119, in as_view if cls.view_is_async: ^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 71, in __get__ return self.fget(cls) ^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\views\generic\base.py", line 73, in view_is_async raise ImproperlyConfigured( django.core.exceptions.ImproperlyConfigured: TestView HTTP handlers must either be all sync or all async.
With hypercorn:
(venv) λ hypercorn myproject.asgi:application [2023-03-31 12:03:33 +0200] [20028] [WARNING] ASGI Framework Lifespan error, continuing without Lifespan support [2023-03-31 12:03:33 +0200] [20028] [INFO] Running on http://127.0.0.1:8000 (CTRL + C to quit) [2023-03-31 12:03:40 +0200] [20028] [ERROR] Error in ASGI Framework Traceback (most recent call last): File "C:\code\myproject\venv\Lib\site-packages\asgiref\sync.py", line 486, in thread_handler raise exc_info[1] File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\exception.py", line 43, in inner response = await get_response(request) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\base.py", line 235, in _get_response_async callback, callback_args, callback_kwargs = self.resolve_request(request) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\base.py", line 313, in resolve_request resolver_match = resolver.resolve(request.path_info) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 663, in resolve for pattern in self.url_patterns: ^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__ res = instance.__dict__[self.name] = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 715, in url_patterns patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module) ^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__ res = instance.__dict__[self.name] = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 708, in urlconf_module return import_module(self.urlconf_name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\Python311\Lib\importlib\__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "<frozen importlib._bootstrap>", line 1206, in _gcd_import File "<frozen importlib._bootstrap>", line 1178, in _find_and_load File "<frozen importlib._bootstrap>", line 1149, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 690, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 940, in exec_module File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed File "C:\code\myproject\myproject\urls.py", line 10, in <module> path('test/', TestView.as_view()), ^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\views\generic\base.py", line 119, in as_view if cls.view_is_async: ^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 71, in __get__ return self.fget(cls) ^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\views\generic\base.py", line 73, in view_is_async raise ImproperlyConfigured( django.core.exceptions.ImproperlyConfigured: TestView HTTP handlers must either be all sync or all async. During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\code\myproject\venv\Lib\site-packages\asgiref\sync.py", line 486, in thread_handler raise exc_info[1] File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\exception.py", line 43, in inner response = await get_response(request) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\utils\deprecation.py", line 152, in __acall__ response = response or await self.get_response(request) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\exception.py", line 45, in inner response = await sync_to_async( ^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\asgiref\sync.py", line 448, in __call__ ret = await asyncio.wait_for(future, timeout=None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\Python311\Lib\asyncio\tasks.py", line 442, in wait_for return await fut ^^^^^^^^^ File "C:\Program Files\Python311\Lib\concurrent\futures\thread.py", line 58, in run result = self.fn(*self.args, **self.kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\asgiref\sync.py", line 488, in thread_handler return func(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\exception.py", line 141, in response_for_exception response = handle_uncaught_exception( ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\core\handlers\exception.py", line 182, in handle_uncaught_exception return debug.technical_500_response(request, *exc_info) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\views\debug.py", line 66, in technical_500_response html = reporter.get_traceback_html() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\views\debug.py", line 396, in get_traceback_html c = Context(self.get_traceback_data(), use_l10n=False) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\views\debug.py", line 381, in get_traceback_data c["raising_view_name"] = get_caller(self.request) ^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\views\debug.py", line 99, in get_caller resolver_match = resolve(request.path) ^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\urls\base.py", line 24, in resolve return get_resolver(urlconf).resolve(path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 663, in resolve for pattern in self.url_patterns: ^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__ res = instance.__dict__[self.name] = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 715, in url_patterns patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module) ^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\utils\functional.py", line 57, in __get__ res = instance.__dict__[self.name] = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\django\urls\resolvers.py", line 708, in urlconf_module return import_module(self.urlconf_name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\Python311\Lib\importlib\__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "<frozen importlib._bootstrap>", line 1206, in _gcd_import File "<frozen importlib._bootstrap>", line 1178, in _find_and_load File "<frozen importlib._bootstrap>", line 1149, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 690, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 940, in exec_module File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed File "C:\code\myproject\myproject\urls.py", line 9, in <module> path("api/", api.urls), ^^^^^^^^ File "C:\code\myproject\venv\Lib\site-packages\ninja\main.py", line 379, in urls self._validate() File "C:\code\myproject\venv\Lib\site-packages\ninja\main.py", line 494, in _validate raise ConfigError(msg.strip()) ninja.errors.ConfigError: Looks like you created multiple NinjaAPIs or TestClients To let ninja distinguish them you need to set either unique version or urls_namespace - NinjaAPI(..., version='2.0.0') - NinjaAPI(..., urls_namespace='otherapi') Already registered: ['api-1.0.0'] During handling of the above exception, another exception occurred: ... (the same frame over and over again)
Note:
See TracTickets
for help on using tickets.