summaryrefslogtreecommitdiff
path: root/django/forms
diff options
context:
space:
mode:
authorJohannes Maron <johannes@maron.family>2024-11-07 10:21:25 +0100
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2025-01-02 13:08:13 +0100
commit989329344aabe8ef7a5e55bebfde53f0e00f42e2 (patch)
treed2a8ea553450ecd97cb415d445980e70b199e266 /django/forms
parentb322319f9d779b8726436421daae2862a380061d (diff)
Fixed #35886 -- Added support for object-based form media script assets.
Diffstat (limited to 'django/forms')
-rw-r--r--django/forms/widgets.py50
1 files changed, 49 insertions, 1 deletions
diff --git a/django/forms/widgets.py b/django/forms/widgets.py
index ca5f2724db..9b5ad1b2b9 100644
--- a/django/forms/widgets.py
+++ b/django/forms/widgets.py
@@ -9,7 +9,7 @@ from collections import defaultdict
from graphlib import CycleError, TopologicalSorter
from itertools import chain
-from django.forms.utils import to_current_timezone
+from django.forms.utils import flatatt, to_current_timezone
from django.templatetags.static import static
from django.utils import formats
from django.utils.choices import normalize_choices
@@ -23,6 +23,7 @@ from django.utils.translation import gettext_lazy as _
from .renderers import get_default_renderer
__all__ = (
+ "Script",
"Media",
"MediaDefiningClass",
"Widget",
@@ -62,6 +63,53 @@ class MediaOrderConflictWarning(RuntimeWarning):
@html_safe
+class MediaAsset:
+ element_template = "{path}"
+
+ def __init__(self, path, **attributes):
+ self._path = path
+ self.attributes = attributes
+
+ def __eq__(self, other):
+ # Compare the path only, to ensure performant comparison in Media.merge.
+ return (self.__class__ is other.__class__ and self.path == other.path) or (
+ isinstance(other, str) and self._path == other
+ )
+
+ def __hash__(self):
+ # Hash the path only, to ensure performant comparison in Media.merge.
+ return hash(self._path)
+
+ def __str__(self):
+ return format_html(
+ self.element_template,
+ path=self.path,
+ attributes=flatatt(self.attributes),
+ )
+
+ def __repr__(self):
+ return f"{type(self).__qualname__}({self._path!r})"
+
+ @property
+ def path(self):
+ """
+ Ensure an absolute path.
+ Relative paths are resolved via the {% static %} template tag.
+ """
+ if self._path.startswith(("http://", "https://", "/")):
+ return self._path
+ return static(self._path)
+
+
+class Script(MediaAsset):
+ element_template = '<script src="{path}"{attributes}></script>'
+
+ def __init__(self, src, **attributes):
+ # Alter the signature to allow src to be passed as a keyword argument.
+ super().__init__(src, **attributes)
+
+
+@html_safe
class Media:
def __init__(self, media=None, css=None, js=None):
if media is not None: