from django.http.request import QueryDict
request.POST 和 request.GET 的 QueryDict 在一个正常的请求/响应循环中是不可变的。若要使其改变,需要使用 copy() 方法。from django.utils.datastructures import MultiValueDict
在 MultiValueDict 类的注释中已经给出了常用的使用过程,如下所示:
>>> d = MultiValueDict({'name': ['Adrian', 'Simon'], 'position': ['Developer']})
>>> d['name']
'Simon'
>>> d.getlist('name')
['Adrian', 'Simon']
>>> d.getlist('doesnotexist')
[]
>>> d.getlist('doesnotexist', ['Adrian', 'Simon'])
['Adrian', 'Simon']
>>> d.get('lastname', 'nonexistent')
'nonexistent'
>>> d.setlist('lastname', ['Holovaty', 'Willison'])
对于一个字典来说,最重要的当然是根据键获取值,而 MultiVauleDict 提供了三个重要方法,分别是:__getitem__、get、getlist。下面我们对上述三个方法做简单的介绍。
[]运算符取值。在这里MultiValueDict 是通过重写其父类 dict 来实现的,源码如下:
def __getitem__(self, key):
"""
返回此键的最后一个数据值,如果是空列表,则返回[];
如果没有找到,则引发键错误。
"""
try:
list_ = super().__getitem__(key)
except KeyError:
raise MultiValueDictKeyError(key)
try:
return list_[-1] #获取key对应值的最后一个
except IndexError:
return []
若果 key 不存在时,会抛出异常即 MultiValueDictKeyError 异常;若当一个 key 有多个值时,获取最后一个值。我们在视图中使用 request.GET['a'] 来获取 a 的值,就是使用了__getitem__方法。
def get(self, key, default=None):
"""
返回传递的键的最后一个数据值。如果键不存在
或值为空列表,返回' default '。
"""
try:
val = self[key]
except KeyError:
return default
if val == []:
return default
return val
分析源码可以得知,它首先尝试使用 val=self[key]获取 key 的值,如果获取不到则返回给定的默认值。但是你要注意这里捕获的异常是 KeyError,这个异常是 Python的标准异常类,而 MultiVauleDictKeyError 是它的一个子类。但是 get 和 __getitem__ 只能获取 key 的最后一个值,如果需要获取 key 的所有值就需要使用 getlist 方法。
def _getlist(self, key, default=None, force_list=False):
"""
返回键值的列表。用于在内部操作值列表。
如果force_list为真,返回值的新副本。
"""
try:
values = super().__getitem__(key)
except KeyError:
if default is None:
return []
return default
else:
if force_list:
values = list(values) if values is not None else None
return values
首选对源码进行初步分析,_getlist调用父类的__getitem__方法获取 key 对应的 values,如果不存在 key,则考虑使用 default。最后,force_list 的作用是将 values 复制一份,并保存在 values 变量中。
QueryDict.__init__(query_string=None, mutable=False, encoding=None)
其中 mutable=False 表示对象不可变,反之则可变。如果把 URL 中的查询字符串直接传递给 QueryDict,会得到如下结果:
In [1]: from django.http.request import QueryDict
In [2]: QueryDict("a=1&b=2&c=3")
Out[2]: <QueryDict: {'a': ['1'], 'b': ['2'], 'c': ['3']}>
这就是通过 QueryDict 构造函数实现,如果感兴趣的小伙伴可以研究一下它的源码,就可以知道它的代码逻辑了,在这里不做分析。下面我们介绍一下它的经常用到的方法。
QueryDict.fromkeys(iterable, value='', mutable=False, encoding=None)
实例如下:
In [4]: QueryDict.fromkeys(['a','b','c'],value="1")
Out[4]: <QueryDict: {'a': ['1'], 'b': ['1'], 'c': ['1']}>
In [11]: QueryDict('a=1&b=2&c=3',mutable=True).pop("a")
Out[11]: ['1']
In [12]: q = QueryDict('a=1&a=2&c=3', mutable=True)
In [13]: q.popitem()
Out[13]: ('c', ['3'])
In [26]: q = QueryDict('a=1&a=2&a=3')
In [27]: q.items()
Out[27]: <generator object MultiValueDict.items at 0x01594AF0>
In [28]: list(q.items())
Out[28]: [('a', '3')]
In [23]: q = QueryDict('a=1&a=2&a=3')
In [24]: q.values()
Out[24]: <generator object MultiValueDict.values at 0x09D578F0>
In [25]: list(q.values())
Out[25]: ['3']
In [29]: q = QueryDict('a=2&b=3&b=5')
In [30]: q.urlencode()
Out[30]: 'a=2&b=3&b=5'
提示:使用 safe 参数传递不需要编码的字符,如 q.urlencode(safe='?')。
In [31]: q = QueryDict('a=1', mutable=True)
In [32]: q.update({'a': '2'})
In [33]: q.getlist('a')
Out[33]: ['1', '2']
本节对 QueryDict 做了详细的讲解,分别从继承关系上进行了分析,大家看完本节,应该能够熟练掌握它的使用方法,而且对于类字典对象也不再感到陌生。当然还有一部分方法没有介绍,有兴趣的伙伴可以参阅官方文档《QueryDict Object》进行学习。
版权说明:Copyright © 广州松河信息科技有限公司 2005-2025 版权所有 粤ICP备16019765号
广州松河信息科技有限公司 版权所有