跳转到主要内容

临时包以在lookupy中发布模型支持

项目描述

Lookupy是一个Python库,提供了一个类似Django QuerySet的接口,用于查询(过滤和选择)数据(字典列表)。

它最初是一个用于解析和提取HAR(HTTP存档)文件中有用数据的库,但在路上我觉得一个通用的库可能很有用,因为我经常发现自己试图从如Facebook或GitHub API获得的JSON集合中获取数据。我选择模仿Django queryset API,因为我熟悉它。

我不总是使用这个库,但当我与深度嵌套的json/dicts(如Facebook、GitHub等API返回的那种)一起工作时,我发现它很有帮助。对于日常事物,我更喜欢Python内置的函数式结构,如map、filter、列表推导式。

需求

  • Python [已测试2.7和3.2]

  • nose [可选,用于运行测试]

  • coverage.py [可选,用于测试覆盖率]

  • Tox [可选,用于在不同的Python版本上构建和测试]

安装

安装此库最简单的方法是使用pip

$ pip install lookupy
提示! 考虑在

虚拟环境

快速入门

由于此库基于Django QuerySets,首先了解它们是如何工作将会有所帮助。在Django中,QuerySets用于构建SQL查询以从数据库中获取数据。使用QuerySet对象的filter方法相当于编写SQL中的WHERE子句。

将相同的概念应用于简单的数据集合(字典列表),lookupy 可以根据使用所谓的“查找参数”指定的某些标准来提取数据子集。

但是首先,我们需要根据以下方式从数据集中构建一个 Collection 对象:

>>> from lookupy import Collection, Q
>>> data = [{'framework': 'Django', 'language': 'Python', 'type': 'full-stack'},
...         {'framework': 'Flask', 'language': 'Python', 'type': 'micro'},
...         {'framework': 'Rails', 'language': 'Ruby', 'type': 'full-stack'},
...         {'framework': 'Sinatra', 'language': 'Ruby', 'type': 'micro'},
...         {'framework': 'Zend', 'language': 'PHP', 'type': 'full-stack'},
...         {'framework': 'Slim', 'language': 'PHP', 'type': 'micro'}]
>>> c = Collection(data)

为了从集合中过滤一些数据,我们调用 filter 方法并将查找参数传递给它。

>>> c.filter(framework__startswith='S')
<lookupy.lookupy.QuerySet object at 0xb740d40c>

>>> list(c.filter(framework__startswith='S'))
[{'framework': 'Sinatra', 'type': 'micro', 'language': 'Ruby'},
{'framework': 'Slim', 'type': 'micro', 'language': 'PHP'}]

查找参数基本上就像一个条件语句,其形式为 <key>__<lookuptype>=<value>,其中 <key> 是字典中的一个键,<lookuptype> 是一组预定义的关键字之一,用于指定如何将 <value> 与每个字典中对应键的实际值进行匹配。请参阅 查找类型列表

默认情况下,通过作为参数传递的多个查找是使用 and 逻辑运算符组合的(稍后我们将看到 ornot 也是支持的)

>>> list(c.filter(framework__startswith='S', language__exact='Ruby'))
[{'framework': 'Sinatra', 'type': 'micro', 'language': 'Ruby'}]

对于 ornot,我们可以使用 Q 对象来组合复杂的查找,并将它们作为位置参数传递,同时将查找参数作为关键字参数传递。不出所料,位运算符 &|~ 被重载以分别作为逻辑运算符 andornot(正如在 Django 中的那样工作)。

>>> list(c.filter(Q(language__exact='Python') | Q(language__exact='Ruby')))
[{'framework': 'Django', 'language': 'Python', 'type': 'full-stack'},
 {'framework': 'Flask', 'language': 'Python', 'type': 'micro'},
 {'framework': 'Rails', 'language': 'Ruby', 'type': 'full-stack'},
 {'framework': 'Sinatra', 'language': 'Ruby', 'type': 'micro'}]
>>> list(c.filter(~Q(language__startswith='R'), framework__endswith='go'))
[{'framework': 'Django', 'language': 'Python', 'type': 'full-stack'}]

Lookupy 还支持通过在 QuerySet 对象上提供 select 方法来使结果只包含所选字段。

在 QuerySet 上调用 filter 或 select 方法将返回另一个 QuerySet,因此可以将这些调用链接在一起。内部上,过滤和选择利用 Python 的生成器进行延迟评估。此外,QuerySetCollection 都实现了 迭代器协议,因此在消耗之前不会进行任何评估。

>>> result = c.filter(Q(language__exact='Python') | Q(language__exact='Ruby')) \
              .filter(framework__istartswith='s')) \
              .select('framework')
>>> for item in result: # <-- this is where filtering will happen
...     print(item)
...
[{'framework': 'Sinatra'}]

对于嵌套字典,查找参数中的键可以使用双下划线构建,例如 request__status__exact=404。最后,也可以使用相同的 Q 对象通过嵌套键值对集合来过滤数据。

>>> data = [{'a': 'python', 'b': {'p': 1, 'q': 2}, 'c': [{'name': 'version', 'value': '3.4'}, {'name': 'author', 'value': 'Guido van Rossum'}]},
...         {'a': 'erlang', 'b': {'p': 3, 'q': 4}, 'c': [{'name': 'version', 'value': 'R16B01'}, {'name': 'author', 'y': 'Joe Armstrong'}]}]
>>> c = Collection(data)
>>> list(c.filter(b__q__gte=4))
[{'a': 'erlang', 'c': [{'name': 'version', 'value': 'R16B01'}, {'y': 'Joe Armstrong', 'name': 'author'}], 'b': {'q': 4, 'p': 3}}]
>>> list(c.filter(c__filter=Q(name='version', value__contains='.')))
[{'a': 'python', 'c': [{'name': 'version', 'value': '3.4'}, {'name': 'author', 'value': 'Guido van Rossum'}], 'b': {'q': 2, 'p': 1}}]

在最后一个示例中,我们使用 Q 对象通过嵌套键值对集合过滤原始字典,即我们只查询版本字符串中包含点(.)的语言。请注意,这与过滤嵌套集合本身不同。为此,我们可以轻松地为子集合构建 Collection 对象。

请参阅 examples 子目录以获取更多使用示例。

支持的查找类型

以下是当前支持的查找类型:

  • exact 精确等于(默认)

  • neq 不相等

  • contains 包含

  • icontains 不区分大小写的包含

  • in 成员

  • startswith 字符串开头

  • istartswith 不区分大小写的开头

  • endswith 字符串结尾

  • iendswith 不区分大小写的结尾

  • gt 大于

  • gte 大于等于

  • lt 小于

  • lte 小于等于

  • regex 正则表达式搜索

  • filter 嵌套过滤

注意!

  1. 如果将不存在的 key 传递给 select,则它将以值 None 包含在所有结果中。

  2. 如果将不存在的 key 传递给 filter,则查找将始终失败。起初,这似乎与第一个点不一致,但这样做是为了保持整体行为可预测。例如,如果使用 lt 查找整数,例如 2 作为值,则查找将始终失败,尽管在 Python 2 中 None < 2 == True。最好的办法是避免这种局面。

  3. 由于目前select的工作方式,如果与filter链式使用,应在其之后而不是之前调用(除非用于查找的键也正在被选择)。我计划在后续版本中修复此问题。

运行测试

$ make test

为了方便在所有环境中(Python 2.7和3.2)进行测试,请运行:

$ tox

待办事项

  • 测量大数据集的性能

  • 实现JSON文件的命令行界面

许可证

本库按现状提供,受MIT许可证约束。

项目详情


下载文件

下载适用于您平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。

源分发

lookupy-unmanaged-0.4.tar.gz (10.9 kB 查看散列值)

上传时间

由以下机构支持