A Flask extension for creating standard resource searches
Project description
Flask-Filter
Filtering Extension for Flask / SQLAlchemy
Check out our GitHub Pages site for the full documentation.
Flask-Filter is a simple Flask extension for standardizing behavior of REST API resource search endpoints. It is designed to integrate with the Flask-SQLAlchemy extension and Marshmallow, a popular serialization library.
Out-of-the-box, Flask-Filter provides search functionality on top-level object fields via an array of filter objects provided in the JSON body of a POST request. For configuring filtering on derived or nested fields see the "Filtering on Nested Fields" section of the documentation.
Installation
Flask-Filter is available on PyPi. To use this library, we recommend you install it via pip:
(venv)$ pip install flask-filter
Default Filters
Flask-Filter supports searching resources based on an array of filters, JSON objects with the following structure:
{"field": "<field_name>", "op": "<operator>", "value": "<some_value>"}
The built-in filters support the following operators:
symbol | operator | python filter class |
---|---|---|
< | less-than | LTFilter |
<= | less-than or equal to | LTEFilter |
= | equal to | EqualsFilter |
> | greater-than | GTFilter |
>= | greater-than or equal to | GTEFilter |
in | in | InFilter |
!= | not equal to | NotEqualsFilter |
like | like | LikeFilter |
contains | many-to-many associated | ContainsFilter |
Note: Be careful with typing around comparator operators. This version does not provide rigorous type-checking, which could cause problems for a user who submits a search like "find Pets with name greater than 'Fido'"
Many-to-many associations can be searched using the contains
operator.
For a Dog object with a many-to-many relationship with "favorite toys"
defined as Dog.toys = [Toy(), Toy()], you can set the field to "toys.name",
the operator to "contains" and the value to "Tennis Ball". This will perform
a SQL "any" search on that field / value and return any Dog objects who like
tennis balls.
Examples
This section demonstrates simplified use-cases for Flask-Filter. For
a complete example app (a Pet Store API), see the /example
folder.
Note: examples in this readme define simple /search
endpoints that
assume a working Flask app has already been initialized, and other
required classes have been defined in a pet_store
directory. To see
a full implementation, go to /examples/pet_store
Example 1: Manually implementing filters in a flask view
Using the FilterSchema
class directly, you can deserialize an
array of JSON filters into a list of flask_filter.Filter
objects
and directly apply the filters using Filter.apply
to craft a
SQLAlchemy query with a complex set of filters.
filter_schema = FilterSchema()
pet_schema = PetSchema()
@app.route('/api/v1/pets/search', methods=['POST'])
def pet_search():
filters = filter_schema.load(request.json.get("filters"), many=True)
query = Pet.query
for f in filters:
query = f.apply(query, Pet, PetSchema)
return jsonify(pet_schema.dump(query.all())), 200
Example 2: Automatically filtering using the query_with_filters
function
from flask_filter import query_with_filters
pet_schema = PetSchema()
@app.route('/api/v1/pets/search', methods=['POST']
def pet_search():
pets = query_with_filters(Pet, request.json.get("filters"), PetSchema)
return jsonify(pet_schema.dump(pets)), 200
Example 3: Initializing and using the Flask extension object
from flask import Flask
from pet_store import Pet, PetSchema # Model defined as subclass of `db.Model`
from pet_store.extensions import db, filtr # SQLAlchemy and FlaskFilter objects
app = Flask(__name__)
db.init_app(app)
filtr.init_app(app)
@app.route('/api/v1/pets/search', methods=['POST'])
def pet_search():
pets = filtr.search(Pet, request.json.get("filters"), PetSchema)
return jsonify(pet_schema.dump(pets)), 200
or alternatively, if you pre-register the Model and Schema with the
FlaskFilter
object you do not need to pass the Schema
directly to
the search
method:
filtr.register_model(Dog, DogSchema) # Register in the app factory
followed by the search execution (without an explicitly-defined schema):
pets = filtr.search(Pet, request.json.get("filters"))
Example 4: Ordering Search Responses
By default, searches return objects ordered on id
, ascending. This behavior
can be customized with the optional order_by
argument.
If you don't have an id
parameter for your database objects or you wish to
sort by other fields, you should populate the order_by
argument to the search
function when you call it.
This approach does not allow API consumers to set the order_by argument, but allows the developer to override the default id ordering.
@app.route('/api/v1/pets/search', methods=['POST'])
def pet_search():
pets = filtr.search(Pet, request.json.get("filters"), PetSchema,
order_by=Pet.name)
return jsonify(pet_schema.dump(pets)), 200
Alternatively, if you wish to allow users to customize the order of the
objects in the response, use a string for the order_by
argument.
@app.route('/api/v1/pets/search', methods=['POST'])
def pet_search():
order_by = json.get("orderBy") or "name"
pets = filtr.search(Pet, request.json.get("filters"), PetSchema,
order_by=order_by)
return jsonify(pet_schema.dump(pets)), 200
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file Flask-Filter-0.1.2a3.tar.gz
.
File metadata
- Download URL: Flask-Filter-0.1.2a3.tar.gz
- Upload date:
- Size: 7.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.9.14
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | d3c65f44585ca5adaf32a0a1c0999c147b0d07f3abea0b722bd54f7c27955908 |
|
MD5 | e09ca51161be5b3b7390922db1696171 |
|
BLAKE2b-256 | 34d4fefebb436a4079c5f6f8ab73b64e9e7e3f74f34521f0d06d4f2e5a0b32e9 |
File details
Details for the file Flask_Filter-0.1.2a3-py3-none-any.whl
.
File metadata
- Download URL: Flask_Filter-0.1.2a3-py3-none-any.whl
- Upload date:
- Size: 8.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.9.14
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | e69ec29eb562f108602467515ff73eb42cd658d3429f1f0edeee83bcca3493c5 |
|
MD5 | 89d798b6926161522860badc7fb07c49 |
|
BLAKE2b-256 | ec03a2482b9b76da582a9689684d84b5b730d4bef94e6fc77887fa538fd1296d |