summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Smith <smithdc@gmail.com>2020-08-30 13:44:39 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2020-09-24 13:53:06 +0200
commit599f2f79e22aaa475e45b72768babf70ac71a6b2 (patch)
tree89974d8358d76832ec25fbf8c7a3981bb4e8c653
parent1ac337cca61570ed64acf02e1700483f7fd02cf6 (diff)
Fixed #30563 -- Optimized form Media by removing duplicated assets when adding.
-rw-r--r--django/forms/widgets.py10
-rw-r--r--tests/forms_tests/tests/test_media.py54
2 files changed, 62 insertions, 2 deletions
diff --git a/django/forms/widgets.py b/django/forms/widgets.py
index 7ea3c7bcbf..1b1c1439cb 100644
--- a/django/forms/widgets.py
+++ b/django/forms/widgets.py
@@ -146,8 +146,14 @@ class Media:
def __add__(self, other):
combined = Media()
- combined._css_lists = self._css_lists + other._css_lists
- combined._js_lists = self._js_lists + other._js_lists
+ combined._css_lists = self._css_lists[:]
+ combined._js_lists = self._js_lists[:]
+ for item in other._css_lists:
+ if item and item not in self._css_lists:
+ combined._css_lists.append(item)
+ for item in other._js_lists:
+ if item and item not in self._js_lists:
+ combined._js_lists.append(item)
return combined
diff --git a/tests/forms_tests/tests/test_media.py b/tests/forms_tests/tests/test_media.py
index 7d8f978ecd..26f81a4602 100644
--- a/tests/forms_tests/tests/test_media.py
+++ b/tests/forms_tests/tests/test_media.py
@@ -592,3 +592,57 @@ class FormsMediaTestCase(SimpleTestCase):
# Media ordering does not matter.
merged = widget1 + widget4
self.assertEqual(merged._css, {'screen': ['c.css'], 'all': ['d.css', 'e.css']})
+
+ def test_add_js_deduplication(self):
+ widget1 = Media(js=['a', 'b', 'c'])
+ widget2 = Media(js=['a', 'b'])
+ widget3 = Media(js=['a', 'c', 'b'])
+ merged = widget1 + widget1
+ self.assertEqual(merged._js_lists, [['a', 'b', 'c']])
+ self.assertEqual(merged._js, ['a', 'b', 'c'])
+ merged = widget1 + widget2
+ self.assertEqual(merged._js_lists, [['a', 'b', 'c'], ['a', 'b']])
+ self.assertEqual(merged._js, ['a', 'b', 'c'])
+ # Lists with items in a different order are preserved when added.
+ merged = widget1 + widget3
+ self.assertEqual(merged._js_lists, [['a', 'b', 'c'], ['a', 'c', 'b']])
+ msg = (
+ "Detected duplicate Media files in an opposite order: "
+ "['a', 'b', 'c'], ['a', 'c', 'b']"
+ )
+ with self.assertWarnsMessage(RuntimeWarning, msg):
+ merged._js
+
+ def test_add_css_deduplication(self):
+ widget1 = Media(css={'screen': ['a.css'], 'all': ['b.css']})
+ widget2 = Media(css={'screen': ['c.css']})
+ widget3 = Media(css={'screen': ['a.css'], 'all': ['b.css', 'c.css']})
+ widget4 = Media(css={'screen': ['a.css'], 'all': ['c.css', 'b.css']})
+ merged = widget1 + widget1
+ self.assertEqual(merged._css_lists, [{'screen': ['a.css'], 'all': ['b.css']}])
+ self.assertEqual(merged._css, {'screen': ['a.css'], 'all': ['b.css']})
+ merged = widget1 + widget2
+ self.assertEqual(merged._css_lists, [
+ {'screen': ['a.css'], 'all': ['b.css']},
+ {'screen': ['c.css']},
+ ])
+ self.assertEqual(merged._css, {'screen': ['a.css', 'c.css'], 'all': ['b.css']})
+ merged = widget3 + widget4
+ # Ordering within lists is preserved.
+ self.assertEqual(merged._css_lists, [
+ {'screen': ['a.css'], 'all': ['b.css', 'c.css']},
+ {'screen': ['a.css'], 'all': ['c.css', 'b.css']}
+ ])
+ msg = (
+ "Detected duplicate Media files in an opposite order: "
+ "['b.css', 'c.css'], ['c.css', 'b.css']"
+ )
+ with self.assertWarnsMessage(RuntimeWarning, msg):
+ merged._css
+
+ def test_add_empty(self):
+ media = Media(css={'screen': ['a.css']}, js=['a'])
+ empty_media = Media()
+ merged = media + empty_media
+ self.assertEqual(merged._css_lists, [{'screen': ['a.css']}])
+ self.assertEqual(merged._js_lists, [['a']])