Changeset 1504
- Timestamp:
- 11/29/05 22:08:46 (3 years ago)
- Files:
-
- django/trunk/django/contrib/admin/views/main.py (modified) (3 diffs)
- django/trunk/django/core/meta/__init__.py (modified) (6 diffs)
- django/trunk/django/utils/datastructures.py (modified) (3 diffs)
- django/trunk/django/utils/httpwrappers.py (modified) (1 diff)
- django/trunk/docs/request_response.txt (modified) (5 diffs)
- django/trunk/tests/othertests/httpwrappers.py (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/trunk/django/contrib/admin/views/main.py
r1489 r1504 58 58 self.get_search_parameters(request) 59 59 self.get_ordering() 60 self.query = request.GET.get(SEARCH_VAR, '')60 self.query = request.GET.get(SEARCH_VAR, '') 61 61 self.get_lookup_params() 62 62 self.get_results(request) … … 101 101 # Get search parameters from the query string. 102 102 try: 103 self.req_get = request.GET104 103 self.page_num = int(request.GET.get(PAGE_VAR, 0)) 105 104 except ValueError: … … 107 106 self.show_all = request.GET.has_key(ALL_VAR) 108 107 self.is_popup = request.GET.has_key(IS_POPUP_VAR) 109 self.params = dict( request.GET.copy())108 self.params = dict((k, v) for k, v in request.GET.items()) 110 109 if self.params.has_key(PAGE_VAR): 111 110 del self.params[PAGE_VAR] django/trunk/django/core/meta/__init__.py
r1485 r1504 1679 1679 params[f.attname] = param 1680 1680 1681 1682 1681 if change: 1683 1682 params[opts.pk.attname] = self.obj_key … … 1711 1710 self.fields_changed.append(f.verbose_name) 1712 1711 1713 expanded_data = DotExpandedDict( new_data.data)1712 expanded_data = DotExpandedDict(dict(new_data)) 1714 1713 # Save many-to-one objects. Example: Add the Choice objects for a Poll. 1715 1714 for related in opts.get_all_related_objects(): … … 1724 1723 obj_list.sort(lambda x, y: cmp(int(x[0]), int(y[0]))) 1725 1724 params = {} 1726 1727 1725 1728 1726 # For each related item... … … 1770 1768 params[f.attname] = param 1771 1769 1772 1773 1770 # Related links are a special case, because we have to 1774 1771 # manually set the "content_type_id" and "object_id" fields. … … 1780 1777 # Create the related item. 1781 1778 new_rel_obj = related.opts.get_model_module().Klass(**params) 1782 1783 1784 1779 1785 1780 # If all the core fields were provided (non-empty), save the item. … … 1814 1809 new_rel_obj.delete() 1815 1810 self.fields_deleted.append('%s "%s"' % (related.opts.verbose_name, old_rel_obj)) 1816 1817 1811 1818 1812 # Save the order, if applicable. django/trunk/django/utils/datastructures.py
r1498 r1504 44 44 pass 45 45 46 class MultiValueDict :46 class MultiValueDict(dict): 47 47 """ 48 A dictionary-like class customized to deal withmultiple values for the same key.48 A subclass of dictionary customized to handle multiple values for the same key. 49 49 50 50 >>> d = MultiValueDict({'name': ['Adrian', 'Simon'], 'position': ['Developer']}) … … 61 61 single name-value pairs. 62 62 """ 63 def __init__(self, key_to_list_mapping=None): 64 self.data = key_to_list_mapping or {} 65 66 def __repr__(self): 67 return repr(self.data) 63 def __init__(self, key_to_list_mapping=()): 64 dict.__init__(self, key_to_list_mapping) 68 65 69 66 def __getitem__(self, key): 70 "Returns the data value for this key; raises KeyError if not found" 71 if self.data.has_key(key): 72 try: 73 return self.data[key][-1] # in case of duplicates, use last value ([-1]) 74 except IndexError: 75 return [] 76 raise MultiValueDictKeyError, "Key '%s' not found in MultiValueDict %s" % (key, self.data) 67 """ 68 Returns the last data value for this key, or [] if it's an empty list; 69 raises KeyError if not found. 70 """ 71 try: 72 list_ = dict.__getitem__(self, key) 73 except KeyError: 74 raise MultiValueDictKeyError, "Key %r not found in MultiValueDict %r" % (key, self) 75 try: 76 return list_[-1] 77 except IndexError: 78 return [] 77 79 78 def __setitem__(self, key, value): 79 self.data[key] = [value] 80 def _setitem_list(self, key, value): 81 dict.__setitem__(self, key, [value]) 82 __setitem__ = _setitem_list 80 83 81 def __len__(self): 82 return len(self.data) 83 84 def __contains__(self, key): 85 return self.data.has_key(key) 86 87 def get(self, key, default): 84 def get(self, key, default=None): 88 85 "Returns the default value if the requested data doesn't exist" 89 86 try: 90 87 val = self[key] 91 except (KeyError, IndexError):88 except KeyError: 92 89 return default 93 90 if val == []: … … 98 95 "Returns an empty list if the requested data doesn't exist" 99 96 try: 100 return self.data[key]97 return dict.__getitem__(self, key) 101 98 except KeyError: 102 99 return [] 103 100 104 101 def setlist(self, key, list_): 105 self.data[key] = list_102 dict.__setitem__(self, key, list_) 106 103 107 def appendlist(self, key, item): 104 def setdefault(self, key, default=None): 105 if key not in self: 106 self[key] = default 107 return self[key] 108 109 def setlistdefault(self, key, default_list=()): 110 if key not in self: 111 self.setlist(key, default_list) 112 return self.getlist(key) 113 114 def appendlist(self, key, value): 108 115 "Appends an item to the internal list associated with key" 109 try: 110 self.data[key].append(item) 111 except KeyError: 112 self.data[key] = [item] 113 114 def has_key(self, key): 115 return self.data.has_key(key) 116 self.setlistdefault(key, []) 117 dict.__setitem__(self, key, self.getlist(key) + [value]) 116 118 117 119 def items(self): 118 # we don't just return self.data.items() here, because we want to use 119 # self.__getitem__() to access the values as *strings*, not lists 120 return [(key, self[key]) for key in self.data.keys()] 120 """ 121 Returns a list of (key, value) pairs, where value is the last item in 122 the list associated with the key. 123 """ 124 return [(key, self[key]) for key in self.keys()] 121 125 122 def keys(self): 123 return self.data.keys() 126 def lists(self): 127 "Returns a list of (key, list) pairs." 128 return dict.items(self) 129 130 def values(self): 131 "Returns a list of the last value on every key list." 132 return [self[key] for key in self.keys()] 133 134 def copy(self): 135 "Returns a copy of this object." 136 import copy 137 # Our custom __setitem__ must be disabled for copying machinery. 138 MultiValueDict.__setitem__ = dict.__setitem__ 139 cp = copy.deepcopy(self) 140 MultiValueDict.__setitem__ = MultiValueDict._setitem_list 141 return cp 124 142 125 143 def update(self, other_dict): 144 "update() extends rather than replaces existing key lists." 126 145 if isinstance(other_dict, MultiValueDict): 127 for key, value_list in other_dict.data.items(): 128 self.data.setdefault(key, []).extend(value_list) 129 elif type(other_dict) == type({}): 130 for key, value in other_dict.items(): 131 self.data.setdefault(key, []).append(value) 146 for key, value_list in other_dict.lists(): 147 self.setlistdefault(key, []).extend(value_list) 132 148 else: 133 raise ValueError, "MultiValueDict.update() takes either a MultiValueDict or dictionary" 134 135 def copy(self): 136 "Returns a copy of this object" 137 import copy 138 cp = copy.deepcopy(self) 139 return cp 149 try: 150 for key, value in other_dict.items(): 151 self.setlistdefault(key, []).append(value) 152 except TypeError: 153 raise ValueError, "MultiValueDict.update() takes either a MultiValueDict or dictionary" 140 154 141 155 class DotExpandedDict(dict): django/trunk/django/utils/httpwrappers.py
r1503 r1504 68 68 This is immutable unless you create a copy of it.""" 69 69 def __init__(self, query_string): 70 if not query_string: 71 self.data = {} 72 self._keys = [] 73 else: 74 self.data = {} 75 self._keys = [] 76 for name, value in parse_qsl(query_string, True): # keep_blank_values=True 77 if name in self.data: 78 self.data[name].append(value) 79 else: 80 self.data[name] = [value] 81 if name not in self._keys: 82 self._keys.append(name) 70 MultiValueDict.__init__(self) 71 self._mutable = True 72 for key, value in parse_qsl(query_string, True): # keep_blank_values=True 73 self.appendlist(key, value) 83 74 self._mutable = False 84 75 85 def _ _setitem__(self, key, value):76 def _assert_mutable(self): 86 77 if not self._mutable: 87 78 raise AttributeError, "This QueryDict instance is immutable" 88 else: 89 self.data[key] = [value] 90 if not key in self._keys: 91 self._keys.append(key) 79 80 def _setitem_if_mutable(self, key, value): 81 self._assert_mutable() 82 MultiValueDict.__setitem__(self, key, value) 83 __setitem__ = _setitem_if_mutable 92 84 93 85 def setlist(self, key, list_): 94 if not self._mutable: 95 raise AttributeError, "This QueryDict instance is immutable" 96 else: 97 self.data[key] = list_ 98 if not key in self._keys: 99 self._keys.append(key) 86 self._assert_mutable() 87 MultiValueDict.setlist(self, key, list_) 88 89 def appendlist(self, key, value): 90 self._assert_mutable() 91 MultiValueDict.appendlist(self, key, value) 92 93 def update(self, other_dict): 94 self._assert_mutable() 95 MultiValueDict.update(self, other_dict) 96 97 def pop(self, key): 98 self._assert_mutable() 99 return MultiValueDict.pop(self, key) 100 101 def popitem(self): 102 self._assert_mutable() 103 return MultiValueDict.popitem(self) 104 105 def clear(self): 106 self._assert_mutable() 107 MultiValueDict.clear(self) 108 109 def setdefault(self, *args): 110 self._assert_mutable() 111 return MultiValueDict.setdefault(self, *args) 100 112 101 113 def copy(self): 102 "Returns a mutable copy of this object" 103 cp = MultiValueDict.copy(self) 114 "Returns a mutable copy of this object." 115 import copy 116 # Our custom __setitem__ must be disabled for copying machinery. 117 QueryDict.__setitem__ = dict.__setitem__ 118 cp = copy.deepcopy(self) 119 QueryDict.__setitem__ = QueryDict._setitem_if_mutable 104 120 cp._mutable = True 105 121 return cp 106 122 107 def assert_synchronized(self):108 assert(len(self._keys) == len(self.data.keys())), \109 "QueryDict data structure is out of sync: %s %s" % (str(self._keys), str(self.data))110 111 def items(self):112 "Respect order preserved by self._keys"113 self.assert_synchronized()114 items = []115 for key in self._keys:116 if key in self.data:117 items.append((key, self.data[key][0]))118 return items119 120 def keys(self):121 self.assert_synchronized()122 return self._keys123 124 123 def urlencode(self): 125 124 output = [] 126 for k, list_ in self. data.items():125 for k, list_ in self.lists(): 127 126 output.extend([urlencode({k: v}) for v in list_]) 128 127 return '&'.join(output) django/trunk/docs/request_response.txt
r1498 r1504 141 141 directly. 142 142 143 ``QueryDict`` implements the following standard dictionary methods: 144 145 * ``__repr__()`` 143 ``QueryDict`` implements the all standard dictionary methods, because it's a 144 subclass of dictionary. Exceptions are outlined here: 146 145 147 146 * ``__getitem__(key)`` -- Returns the value for the given key. If the key … … 149 148 150 149 * ``__setitem__(key, value)`` -- Sets the given key to ``[value]`` 151 (a Python list whose single element is ``value``). 152 153 * ``__contains__(key)`` -- **New in Django development version.*** Returns 154 ``True`` if the given key exists. This lets you do, e.g., 150 (a Python list whose single element is ``value``). Note that this, as 151 other dictionary functions that have side effects, can only be called on 152 an immutable ``QueryDict`` (one that was created via ``copy()``). 153 154 * ``__contains__(key)`` -- **New in Django development version.** Returns 155 ``True`` if the given key is set. This lets you do, e.g., 155 156 ``if "foo" in request.GET``. 156 157 * ``__len__()``158 157 159 158 * ``get(key, default)`` -- Uses the same logic as ``__getitem__()`` above, … … 162 161 * ``has_key(key)`` 163 162 163 * ``setdefault(key, default)`` -- Just like the standard dictionary 164 ``setdefault()`` method, except it uses ``__setitem__`` internally. 165 166 * ``update(other_dict)`` -- Takes either a ``QueryDict`` or standard 167 dictionary. Just like the standard dictionary ``update()`` method, except 168 it *appends* to the current dictionary items rather than replacing them. 169 For example:: 170 171 >>> q = QueryDict('a=1') 172 >>> q = q.copy() # to make it mutable 173 >>> q.update({'a': '2'}) 174 >>> q.getlist('a') 175 ['1', '2'] 176 >>> q['a'] # returns the last 177 ['2'] 178 164 179 * ``items()`` -- Just like the standard dictionary ``items()`` method, 165 except this retains the order for values of duplicate keys, if any. For 166 example, if the original query string was ``"a=1&b=2&b=3"``, ``items()`` 167 will return ``[("a", ["1"]), ("b", ["2", "3"])]``, where the order of 168 ``["2", "3"]`` is guaranteed, but the order of ``a`` vs. ``b`` isn't. 169 170 * ``keys()`` 171 172 * ``update(other_dict)`` 173 174 In addition, it has the following methods: 180 except this uses the same last-value logic as ``__getitem()__``. For 181 example:: 182 183 >>> q = QueryDict('a=1&a=2&a=3') 184 >>> q.items() 185 [('a', '3')] 186 187 * ``values()`` -- Just like the standard dictionary ``values()`` method, 188 except this uses the same last-value logic as ``__getitem()__``. For 189 example:: 190 191 >>> q = QueryDict('a=1&a=2&a=3') 192 >>> q.values() 193 ['3'] 194 195 In addition, ``QueryDict`` has the following methods: 175 196 176 197 * ``copy()`` -- Returns a copy of the object, using ``copy.deepcopy()`` … … 179 200 180 201 * ``getlist(key)`` -- Returns the data with the requested key, as a Python 181 list. Returns an empty list if the key doesn't exist. 202 list. Returns an empty list if the key doesn't exist. It's guaranteed to 203 return a list of some sort. 182 204 183 205 * ``setlist(key, list_)`` -- Sets the given key to ``list_`` (unlike … … 186 208 * ``appendlist(key, item)`` -- Appends an item to the internal list 187 209 associated with key. 210 211 * ``setlistdefault(key, default_list)`` -- Just like ``setdefault``, except 212 it takes a list of values instead of a single value. 213 214 * ``lists()`` -- Like ``items()``, except it includes all values, as a list, 215 for each member of the dictionary. For example:: 216 217 >>> q = QueryDict('a=1&a=2&a=3') 218 >>> q.lists() 219 [('a', ['1', '2', '3'])] 188 220 189 221 * ``urlencode()`` -- Returns a string of the data in query-string format.
