Skip to main content

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.

Python package Coverage Status PyPi

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

Flask-Filter-0.1.2a3.tar.gz (7.4 kB view details)

Uploaded Source

Built Distribution

Flask_Filter-0.1.2a3-py3-none-any.whl (8.6 kB view details)

Uploaded Python 3

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

Hashes for Flask-Filter-0.1.2a3.tar.gz
Algorithm Hash digest
SHA256 d3c65f44585ca5adaf32a0a1c0999c147b0d07f3abea0b722bd54f7c27955908
MD5 e09ca51161be5b3b7390922db1696171
BLAKE2b-256 34d4fefebb436a4079c5f6f8ab73b64e9e7e3f74f34521f0d06d4f2e5a0b32e9

See more details on using hashes here.

File details

Details for the file Flask_Filter-0.1.2a3-py3-none-any.whl.

File metadata

File hashes

Hashes for Flask_Filter-0.1.2a3-py3-none-any.whl
Algorithm Hash digest
SHA256 e69ec29eb562f108602467515ff73eb42cd658d3429f1f0edeee83bcca3493c5
MD5 89d798b6926161522860badc7fb07c49
BLAKE2b-256 ec03a2482b9b76da582a9689684d84b5b730d4bef94e6fc77887fa538fd1296d

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page