Coverage for utilities/htmx.py: 26%

21 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-10 18:35 +0000

1from urllib.parse import urlsplit 

2 

3from django.http import HttpResponse 

4from django.urls import reverse 

5 

6__all__ = ( 

7 'htmx_current_url', 

8 'htmx_maybe_redirect_current_page', 

9 'htmx_partial', 

10) 

11 

12 

13def htmx_partial(request): 

14 """ 

15 Determines whether to render partial (versus complete) HTML content 

16 in response to an HTMX request, based on the target element. 

17 """ 

18 return request.htmx and not request.htmx.boosted 

19 

20 

21def htmx_current_url(request) -> str: 

22 """ 

23 Extracts the current URL from the HTMX-specific headers in the given request object. 

24 

25 This function checks for the `HX-Current-URL` header in the request's headers 

26 and `HTTP_HX_CURRENT_URL` in the META data of the request. It preferentially 

27 chooses the value present in the `HX-Current-URL` header and falls back to the 

28 `HTTP_HX_CURRENT_URL` META data if the former is unavailable. If neither value 

29 exists, it returns an empty string. 

30 """ 

31 return request.headers.get('HX-Current-URL') or request.META.get('HTTP_HX_CURRENT_URL', '') or '' 

32 

33 

34def htmx_maybe_redirect_current_page( 

35 request, url_name: str, *, preserve_query: bool = True, status: int = 200 

36) -> HttpResponse | None: 

37 """ 

38 Redirects the current page in an HTMX request if conditions are met. 

39 

40 This function checks whether a request is an HTMX partial request and if the 

41 current URL matches the provided target URL. If the conditions are met, it 

42 returns an HTTP response signaling a redirect to the provided or updated target 

43 URL. Otherwise, it returns None. 

44 """ 

45 if not htmx_partial(request): 

46 return None 

47 

48 current = urlsplit(htmx_current_url(request)) 

49 target_path = reverse(url_name) # will raise NoReverseMatch if misconfigured 

50 

51 if current.path.rstrip('/') != target_path.rstrip('/'): 

52 return None 

53 

54 redirect_to = target_path 

55 if preserve_query and current.query: 

56 redirect_to = f'{target_path}?{current.query}' 

57 

58 resp = HttpResponse(status=status) 

59 resp['HX-Redirect'] = redirect_to 

60 return resp