{ "info": { "author": "Christoph Brand", "author_email": "christoph@brand.rest", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.1", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5" ], "description": "# Python Filterparams #\n\nFilterparams is a library for parsing URL paramters for filter\npurposes in a backend. It provides a syntax to map SQL-like \nqueries on top of the query parameters and parses it into a\npython object.\n\nThis is a helper library for providing filter collection APIs. \nThe primary use case for developing the library is to\nuse it with a REST-API which uses the [JSONAPI](http://jsonapi.org/) \nstandard. Because of this the syntax is completely compatible with \nthe standard and encapsulates everything in the `filter` query \nparameter.\n\n## Example ##\n\nGiven the URL (non URL escaped for better readability):\n```\n/users?filter[param][name][like][no_default_name]=doe&filter[param][first_name]=doe%&filter[binding]=(!no_brand_name&first_name)&filter[order]=name&filter[order]=desc(first_name)\n```\n\nIt can be parsed by the given function:\n\n```python\nfrom urllib.parse import urlsplit, parse_qs\nfrom filterparams import build_parser\n\nurl = urlsplit(\n '/users?filter[param][name][like][no_default_name]=doe'\n '&filter[param][first_name]=doe%&filter[binding]='\n '(!no_brand_name&first_name)&filter[order]=name'\n '&filter[order]=desc(first_name)'\n)\nparams = parse_qs(url)\n\nvalid_filters = ['eq', 'like']\ndefault_filter = 'eq'\n\nparser = build_parser(\n valid_filters=valid_filters,\n default_filter=default_filter,\n)\n\nquery = parser(params)\n```\n\nWould parse the data. You can access the parsed filters through\n`.param_order` and the orders through `.orders`. The param order\nin this specific case would be resolved to:\n\n```python\nAnd(\n left=Parameter(\n name='name',\n alias='no_default_name',\n filter='like',\n value='doe%',\n ),\n right=Parameter(\n name='first_name',\n alias='first_name',\n filter='eq',\n value='doe',\n )\n)\n```\n\nThe orders would be:\n\n```python\n[Order(name='name', direction='asc'), \n Order(name='first_name', direction='desc')]\n```\n\n## Syntax ##\n\nAll arguments must be prefixed by \"filter\". It is possible to \nquery for specific data with filters, apply orders to the result \nand to combine filters through AND, NOT and OR bindings.\n\nThe syntax builds under the filter parameter a virtual object. \nThe keys of the object are simulated through specifying `[{key}]` \nin the passed query parameter. Thus `filter[param]` would point \nto the param key in the filter object.\n\n### Filter specification ###\n\nThe solution supports to query data through the `param` subkey.\n\n```\nfilter[param][{parameter_name}][{operation}][{alias}] = {to_query_value}\n```\n\nThe `operation` and `alias` parameters may be omitted. If no \n`alias` is provided the given parameter name is used for it.\nIf no `operation` is given, the default one is used (in the \nexample this would be equal).\n\nExample:\n```\nfilter[param][phone_number][like]=001%\n```\n\nThis would add a filter to all phone numbers which start with \"001\".\n\n### Filter binding ###\n\nPer default all filters are combined through AND clauses. \nYou can change that by specifying the `filter[binding]` argument.\n\nThis is where the aliases which you can define come into place. \nThe binding provides means to combine filters with AND and OR. \nAlso you are able to negate filters here.\n\nThe filters are addressed by their alias or name, if no alias is \nprovided.\n\nIf you have a filter `search_for_name`, `search_for_phone_number` \nand `search_for_account_number` defined you can say \n`search_for_name OR NOT search_for_number AND search_for_account_number` \nby specifying the following filter:\n\n```\nfilter[binding]=search_for_name|(!search_for_phone_number&search_for_account_number)\n```\n\nEven though the brackets are useless here, you can use them in \nmore complex filters.\n\nThe following table summarizes the possible configuration options:\n
| Type | \nSymbol | \nExample | \n
|---|---|---|
| AND | \n& | \na&b | \n
| OR | \n| | \na|b | \n
| NOT | \n! | \n!a | \n
| Bracket | \n() | \n(a|b)&c | \n