Skip to content

Commit

Permalink
Fixed #17634 -- Optimized the performance of MultiValueDict by using …
Browse files Browse the repository at this point in the history
…append instead of copy and by minimizing the number of dict lookups. Refs #736.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17464 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
aaugustin committed Feb 9, 2012
1 parent f9ec6bd commit bd58612
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 9 deletions.
21 changes: 12 additions & 9 deletions django/utils/datastructures.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -312,27 +312,30 @@ def getlist(self, key, default=None):
try: try:
return super(MultiValueDict, self).__getitem__(key) return super(MultiValueDict, self).__getitem__(key)
except KeyError: except KeyError:
if default is not None: if default is None:
return default return []
return [] return default


def setlist(self, key, list_): def setlist(self, key, list_):
super(MultiValueDict, self).__setitem__(key, list_) super(MultiValueDict, self).__setitem__(key, list_)


def setdefault(self, key, default=None): def setdefault(self, key, default=None):
if key not in self: if key not in self:
self[key] = default self[key] = default
return default
return self[key] return self[key]


def setlistdefault(self, key, default_list=()): def setlistdefault(self, key, default_list=None):
if key not in self: if key not in self:
if default_list is None:
default_list = []
self.setlist(key, default_list) self.setlist(key, default_list)
return default_list
return self.getlist(key) return self.getlist(key)


def appendlist(self, key, value): def appendlist(self, key, value):
"""Appends an item to the internal list associated with key.""" """Appends an item to the internal list associated with key."""
self.setlistdefault(key, []) self.setlistdefault(key).append(value)
super(MultiValueDict, self).__setitem__(key, self.getlist(key) + [value])


def items(self): def items(self):
""" """
Expand Down Expand Up @@ -381,15 +384,15 @@ def update(self, *args, **kwargs):
other_dict = args[0] other_dict = args[0]
if isinstance(other_dict, MultiValueDict): if isinstance(other_dict, MultiValueDict):
for key, value_list in other_dict.lists(): for key, value_list in other_dict.lists():
self.setlistdefault(key, []).extend(value_list) self.setlistdefault(key).extend(value_list)
else: else:
try: try:
for key, value in other_dict.items(): for key, value in other_dict.items():
self.setlistdefault(key, []).append(value) self.setlistdefault(key).append(value)
except TypeError: except TypeError:
raise ValueError("MultiValueDict.update() takes either a MultiValueDict or dictionary") raise ValueError("MultiValueDict.update() takes either a MultiValueDict or dictionary")
for key, value in kwargs.iteritems(): for key, value in kwargs.iteritems():
self.setlistdefault(key, []).append(value) self.setlistdefault(key).append(value)


def dict(self): def dict(self):
""" """
Expand Down
6 changes: 6 additions & 0 deletions tests/regressiontests/utils/datastructures.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -206,6 +206,12 @@ def test_multivaluedict(self):
self.assertEqual(list(d.itervalues()), self.assertEqual(list(d.itervalues()),
['Developer', 'Simon', 'Willison']) ['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): def test_copy(self):
for copy_func in [copy.copy, lambda d: d.copy()]: for copy_func in [copy.copy, lambda d: d.copy()]:
d1 = MultiValueDict({ d1 = MultiValueDict({
Expand Down

0 comments on commit bd58612

Please sign in to comment.