Source code for django_htmx.http

from __future__ import annotations

import json
from typing import Any, Literal, TypeVar

from django.core.serializers.json import DjangoJSONEncoder
from django.http import HttpResponse
from django.http.response import HttpResponseBase, HttpResponseRedirectBase

HTMX_STOP_POLLING = 286


[docs] class HttpResponseStopPolling(HttpResponse): status_code = HTMX_STOP_POLLING def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self._reason_phrase = "Stop Polling"
[docs] class HttpResponseClientRedirect(HttpResponseRedirectBase): status_code = 200 def __init__(self, redirect_to: str, *args: Any, **kwargs: Any) -> None: super().__init__(redirect_to, *args, **kwargs) self["HX-Redirect"] = self["Location"] del self["Location"] @property def url(self) -> str: return self["HX-Redirect"]
[docs] class HttpResponseClientRefresh(HttpResponse): def __init__(self) -> None: super().__init__() self["HX-Refresh"] = "true"
[docs] class HttpResponseLocation(HttpResponseRedirectBase): status_code = 200 def __init__( self, redirect_to: str, *args: Any, source: str | None = None, event: str | None = None, target: str | None = None, swap: Literal[ "innerHTML", "outerHTML", "beforebegin", "afterbegin", "beforeend", "afterend", "delete", "none", None, ] = None, select: str | None = None, values: dict[str, str] | None = None, headers: dict[str, str] | None = None, **kwargs: Any, ) -> None: super().__init__(redirect_to, *args, **kwargs) spec: dict[str, str | dict[str, str]] = { "path": self["Location"], } del self["Location"] if source is not None: spec["source"] = source if event is not None: spec["event"] = event if target is not None: spec["target"] = target if swap is not None: spec["swap"] = swap if select is not None: spec["select"] = select if headers is not None: spec["headers"] = headers if values is not None: spec["values"] = values self["HX-Location"] = json.dumps(spec)
_HttpResponse = TypeVar("_HttpResponse", bound=HttpResponseBase)
[docs] def push_url(response: _HttpResponse, url: str | Literal[False]) -> _HttpResponse: response["HX-Push-Url"] = "false" if url is False else url return response
[docs] def replace_url(response: _HttpResponse, url: str | Literal[False]) -> _HttpResponse: response["HX-Replace-Url"] = "false" if url is False else url return response
[docs] def reswap(response: _HttpResponse, method: str) -> _HttpResponse: response["HX-Reswap"] = method return response
[docs] def retarget(response: _HttpResponse, target: str) -> _HttpResponse: response["HX-Retarget"] = target return response
[docs] def trigger_client_event( response: _HttpResponse, name: str, params: dict[str, Any] | None = None, *, after: Literal["receive", "settle", "swap"] = "receive", encoder: type[json.JSONEncoder] = DjangoJSONEncoder, ) -> _HttpResponse: params = params or {} if after == "receive": header = "HX-Trigger" elif after == "settle": header = "HX-Trigger-After-Settle" elif after == "swap": header = "HX-Trigger-After-Swap" else: raise ValueError( "Value for 'after' must be one of: 'receive', 'settle', or 'swap'." ) if header in response: value = response[header] try: data = json.loads(value) except json.JSONDecodeError as exc: raise ValueError(f"{header!r} value should be valid JSON.") from exc data[name] = params else: data = {name: params} response[header] = json.dumps(data, cls=encoder) return response