Commits

Anonymous committed 9df8e4a

Fixed #17634 -- Optimized the performance of MultiValueDict by using append instead of copy and by minimizing the number of dict lookups. Refs #736.

Comments (0)

Files changed (2)

django/utils/datastructures.py

         try:
             return super(MultiValueDict, self).__getitem__(key)
         except KeyError:
-            if default is not None:
-                return default
-            return []
+            if default is None:
+                return []
+            return default
 
     def setlist(self, key, list_):
         super(MultiValueDict, self).__setitem__(key, list_)
     def setdefault(self, key, default=None):
         if key not in self:
             self[key] = default
+            return default
         return self[key]
 
-    def setlistdefault(self, key, default_list=()):
+    def setlistdefault(self, key, default_list=None):
         if key not in self:
+            if default_list is None:
+                default_list = []
             self.setlist(key, default_list)
+            return default_list
         return self.getlist(key)
 
     def appendlist(self, key, value):
         """Appends an item to the internal list associated with key."""
-        self.setlistdefault(key, [])
-        super(MultiValueDict, self).__setitem__(key, self.getlist(key) + [value])
+        self.setlistdefault(key).append(value)
 
     def items(self):
         """
             other_dict = args[0]
             if isinstance(other_dict, MultiValueDict):
                 for key, value_list in other_dict.lists():
-                    self.setlistdefault(key, []).extend(value_list)
+                    self.setlistdefault(key).extend(value_list)
             else:
                 try:
                     for key, value in other_dict.items():
-                        self.setlistdefault(key, []).append(value)
+                        self.setlistdefault(key).append(value)
                 except TypeError:
                     raise ValueError("MultiValueDict.update() takes either a MultiValueDict or dictionary")
         for key, value in kwargs.iteritems():
-            self.setlistdefault(key, []).append(value)
+            self.setlistdefault(key).append(value)
 
     def dict(self):
         """

tests/regressiontests/utils/datastructures.py

         self.assertEqual(list(d.itervalues()),
                           ['Developer', 'Simon', 'Willison'])
 
+    def test_appendlist(self):
+        d = MultiValueDict()
+        d.appendlist('name', 'Adrian')
+        d.appendlist('name', 'Simon')
+        self.assertEqual(d.getlist('name'), ['Adrian', 'Simon'])
+
     def test_copy(self):
         for copy_func in [copy.copy, lambda d: d.copy()]:
             d1 = MultiValueDict({
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.