# 过滤 Flask-REST-JSONAPI有非常灵活的过滤系统。过滤系统的操作,完全由ResourceList管理器的数据层提供的接口来实现。这里,我们将介绍SQLAlchemy数据层的过滤接口,同样,我们也可以实现定制的数据层过滤接口。过滤功能的使用,我只需要在url中添加“filter”查询参数即可。当然,语句也必须符合JSONAPI 1.0的规范。 > **注:** > > 为了可读性,以下例子未进行url编码。 ## SQLAlchemy --- SQLAlchemy数据层的过滤系统接口与[Flask-Restless](https://flask-restless.readthedocs.io/en/stable/searchformat.html#query-format)提供的完全一样。以下为第一个例子: ```http GET /persons?filter=[{"name":"name","op":"eq","val":"John"}] HTTP/1.1 Accept: application/vnd.api+json ``` 在这个例子中,我们过滤得到了名为John的人。我们发现,过滤接口其实就是SQLalchemy原生提供的方法:列表+过滤信息。 - name: 我们想要过滤的字段名 - op: 操作符(这要SQLAlchemy提供,就可以使用) - val: 我们想要比较的值。我们也可以在此用“field”替换,即另一个字段,来进行比较。 ```http GET /persons?filter=[{"name":"name","op":"eq","field":"birth_date"}] HTTP/1.1 Accept: application/vnd.api+json ``` 在上面的例子中,我们想要过滤人名和生日一样的人。虽然例子比较搞笑,但我们只是为了解释下这种用法。 如果,我们想要过滤关系型数据,我们可以: ```http GET /persons?filter=[ { "name": "computers", "op": "any", "val": { "name": "serial", "op": "ilike", "val": "%Amstrad%" } } ] HTTP/1.1 Accept: application/vnd.api+json ``` > **注:** > > 当我们过滤关系时,使用“any”操作符来过滤“对多”关系;使用“has”操作符来过滤“对一”关系。 另外,我们也能使用一种快捷的方式实现同样的功能: ```http GET /persons?filter=[{"name":"computers__serial","op":"ilike","val":"%Amstrad%"}] HTTP/1.1 Accept: application/vnd.api+json ``` 我们也能用“与或非”来联结操作: ```http GET /persons?filter=[ { "name":"computers__serial", "op":"ilike", "val":"%Amstrad%" }, { "or": { [ { "not": { "name": "name", "op": "eq", "val":"John" } }, { "and": [ { "name": "name", "op": "like", "val": "%Jim%" }, { "name": "birth_date", "op": "gt", "val": "1990-01-01" } ] } ] } } ] HTTP/1.1 Accept: application/vnd.api+json ``` 常用操作符: - any: 过滤对多关系 - between: 过滤一个字段位于两个值之间 - endswith: 检查是否以某个字符串结尾 - eq: 等于 - ge: 大于或等于 - gt: 大于 - has: 过滤对一关系 - ilike: 检查是否包含某个字符串(大小写不明感) - in_: 检查是否包含在list中 - is_: 检查字段是否是某个值 - isnot: 检查字段是否不是某个值 - like: 检查是否包含某个字符串 - le: 小于或等于 - lt: 小于 - match: 匹配 - ne: 不等于 - notilike: 检查是否不包含某个字符串(大小写不明感) - notin_: 检查是否不包含在list中 - notlike: 检查是否不包含某个字符串 - startswith: 检查是否以某个字符串开始 > **注:** > > 使用常用操作符时,要看model的字段类型是否支持该操作。 ## 简单过滤 --- 简单过滤仅支持“eq”操作符。每个简单过滤语句,都会转换成其默认的过滤语句,并添加到过滤列表的末尾。 例: ```http GET /persons?filter[name]=John HTTP/1.1 Accept: application/vnd.api+json ``` 等同于: ```http GET /persons?filter[name]=[{"name":"name","op":"eq","val":"John"}] HTTP/1.1 Accept: application/vnd.api+json ``` 同样,我们也能在请求中,使用多个简单过滤: ```http GET /persons?filter[name]=John&filter[gender]=male HTTP/1.1 Accept: application/vnd.api+json ``` 等同于: ```http GET /persons?filter[name]=[{"name":"name","op":"eq","val":"John"}, {"name":"gender","op":"eq","val":"male"}] HTTP/1.1 ```