feat: Support both sync and async in ComponentDependencyMiddleware

Co-authored-by: TheSteveBurgess
This commit is contained in:
TheSteveBurgess 2024-05-01 16:01:09 +01:00 committed by GitHub
parent 8ada8ec3c7
commit 0f3491850b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -2,10 +2,12 @@ import re
from collections.abc import Callable from collections.abc import Callable
from typing import TYPE_CHECKING, Iterable from typing import TYPE_CHECKING, Iterable
from asgiref.sync import iscoroutinefunction, markcoroutinefunction
from django.conf import settings from django.conf import settings
from django.forms import Media from django.forms import Media
from django.http import HttpRequest, HttpResponse, StreamingHttpResponse from django.http import HttpRequest, HttpResponse, StreamingHttpResponse
from django.http.response import HttpResponseBase from django.http.response import HttpResponseBase
from django.utils.decorators import sync_and_async_middleware
from django_components.component_registry import registry from django_components.component_registry import registry
@ -25,6 +27,7 @@ PLACEHOLDER_REGEX = re.compile(
) )
@sync_and_async_middleware
class ComponentDependencyMiddleware: class ComponentDependencyMiddleware:
"""Middleware that inserts CSS/JS dependencies for all rendered components at points marked with template tags.""" """Middleware that inserts CSS/JS dependencies for all rendered components at points marked with template tags."""
@ -33,14 +36,32 @@ class ComponentDependencyMiddleware:
def __init__(self, get_response: "Callable[[HttpRequest], HttpResponse]") -> None: def __init__(self, get_response: "Callable[[HttpRequest], HttpResponse]") -> None:
self.get_response = get_response self.get_response = get_response
if iscoroutinefunction(self.get_response):
markcoroutinefunction(self)
def __call__(self, request: HttpRequest) -> HttpResponseBase: def __call__(self, request: HttpRequest) -> HttpResponseBase:
if iscoroutinefunction(self):
return self.__acall__(request)
response = self.get_response(request) response = self.get_response(request)
response = self.process_response(response)
return response
async def __acall__(self, request: HttpRequest) -> HttpResponseBase:
response = await self.get_response(request)
response = self.process_response(response)
return response
def process_response(self, response: HttpResponse) -> HttpResponse:
if ( if (
getattr(settings, "COMPONENTS", {}).get("RENDER_DEPENDENCIES", False) getattr(settings, "COMPONENTS", {}).get("RENDER_DEPENDENCIES", False)
and not isinstance(response, StreamingHttpResponse) and not isinstance(response, StreamingHttpResponse)
and response.get("Content-Type", "").startswith("text/html") and response.get("Content-Type", "").startswith("text/html")
): ):
response.content = process_response_content(response.content) response.content = process_response_content(response.content)
return response return response