Giter Site home page Giter Site logo

sqlalchemy-filters's Introduction

SQLAlchemy filters

Filter, sort and paginate SQLAlchemy query objects. Ideal for exposing these actions over a REST API.

Filtering

Assuming that we have a SQLAlchemy query object:

from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base


class Base(object):
    id = Column(Integer, primary_key=True)
    name = Column(String(50), nullable=False)
    count = Column(Integer, nullable=True)

    @hybrid_property
    def count_square(self):
        return self.count * self.count

    @hybrid_method
    def three_times_count(self):
        return self.count * 3


Base = declarative_base(cls=Base)


class Foo(Base):

    __tablename__ = 'foo'

# ...

query = session.query(Foo)

Then we can apply filters to that query object (multiple times):

from sqlalchemy_filters import apply_filters


# `query` should be a SQLAlchemy query object

filter_spec = [{'field': 'name', 'op': '==', 'value': 'name_1'}]
filtered_query = apply_filters(query, filter_spec)

more_filters = [{'field': 'foo_id', 'op': 'is_not_null'}]
filtered_query = apply_filters(filtered_query, more_filters)

result = filtered_query.all()

It is also possible to filter queries that contain multiple models, including joins:

class Bar(Base):

    __tablename__ = 'bar'

    foo_id = Column(Integer, ForeignKey('foo.id'))
query = session.query(Foo).join(Bar)

filter_spec = [
    {'model': 'Foo', 'field': 'name', 'op': '==', 'value': 'name_1'},
    {'model': 'Bar', 'field': 'count', 'op': '>=', 'value': 5},
]
filtered_query = apply_filters(query, filter_spec)

result = filtered_query.all()

apply_filters will attempt to automatically join models to query if they're not already present and a model-specific filter is supplied. For example, the value of filtered_query in the following two code blocks is identical:

query = session.query(Foo).join(Bar)  # join pre-applied to query

filter_spec = [
    {'model': 'Foo', 'field': 'name', 'op': '==', 'value': 'name_1'},
    {'model': 'Bar', 'field': 'count', 'op': '>=', 'value': 5},
]
filtered_query = apply_filters(query, filter_spec)
query = session.query(Foo)  # join to Bar will be automatically applied

filter_spec = [
    {field': 'name', 'op': '==', 'value': 'name_1'},
    {'model': 'Bar', 'field': 'count', 'op': '>=', 'value': 5},
]
filtered_query = apply_filters(query, filter_spec)

The automatic join is only possible if SQLAlchemy can implictly determine the condition for the join, for example because of a foreign key relationship.

Automatic joins allow flexibility for clients to filter and sort by related objects without specifying all possible joins on the server beforehand. Feature can be explicitly disabled by passing do_auto_join=False argument to the apply_filters call.

Note that first filter of the second block does not specify a model. It is implictly applied to the Foo model because that is the only model in the original query passed to apply_filters.

It is also possible to apply filters to queries defined by fields, functions or select_from clause:

query_alt_1 = session.query(Foo.id, Foo.name)
query_alt_2 = session.query(func.count(Foo.id))
query_alt_3 = session.query().select_from(Foo).add_column(Foo.id)

Hybrid attributes

You can filter by a hybrid attribute: a hybrid property or a hybrid method.

query = session.query(Foo)

filter_spec = [{'field': 'count_square', 'op': '>=', 'value': 25}]
filter_spec = [{'field': 'three_times_count', 'op': '>=', 'value': 15}]

filtered_query = apply_filters(query, filter_spec)
result = filtered_query.all()

Restricted Loads

You can restrict the fields that SQLAlchemy loads from the database by using the apply_loads function:

query = session.query(Foo, Bar).join(Bar)
load_spec = [
    {'model': 'Foo', 'fields': ['name']},
    {'model': 'Bar', 'fields': ['count']}
]
query = apply_loads(query, load_spec)  # will load only Foo.name and Bar.count

The effect of the apply_loads function is to _defer_ the load of any other fields to when/if they're accessed, rather than loading them when the query is executed. It only applies to fields that would be loaded during normal query execution.

Effect on joined queries

The default SQLAlchemy join is lazy, meaning that columns from the joined table are loaded only when required. Therefore apply_loads has limited effect in the following scenario:

query = session.query(Foo).join(Bar)
load_spec = [
    {'model': 'Foo', 'fields': ['name']}
    {'model': 'Bar', 'fields': ['count']}  # ignored
]
query = apply_loads(query, load_spec)  # will load only Foo.name

apply_loads cannot be applied to columns that are loaded as joined eager loads. This is because a joined eager load does not add the joined model to the original query, as explained here

The following would not prevent all columns from Bar being eagerly loaded:

query = session.query(Foo).options(joinedload(Foo.bar))
load_spec = [
    {'model': 'Foo', 'fields': ['name']}
    {'model': 'Bar', 'fields': ['count']}
]
query = apply_loads(query, load_spec)

Automatic Join

In fact, what happens here is that Bar is automatically joined to query, because it is determined that Bar is not part of the original query. The load_spec therefore has no effect because the automatic join results in lazy evaluation.

If you wish to perform a joined load with restricted columns, you must specify the columns as part of the joined load, rather than with apply_loads:

query = session.query(Foo).options(joinedload(Bar).load_only('count'))
load_spec = [
    {'model': 'Foo', 'fields': ['name']}
]
query = apply_loads(query. load_spec)  # will load ony Foo.name and Bar.count

Sort

from sqlalchemy_filters import apply_sort


# `query` should be a SQLAlchemy query object

sort_spec = [
    {'model': 'Foo', 'field': 'name', 'direction': 'asc'},
    {'model': 'Bar', 'field': 'id', 'direction': 'desc'},
]
sorted_query = apply_sort(query, sort_spec)

result = sorted_query.all()

apply_sort will attempt to automatically join models to query if they're not already present and a model-specific sort is supplied. The behaviour is the same as in apply_filters.

This allows flexibility for clients to sort by fields on related objects without specifying all possible joins on the server beforehand.

Hybrid attributes

You can sort by a hybrid attribute: a hybrid property or a hybrid method.

Pagination

from sqlalchemy_filters import apply_pagination


# `query` should be a SQLAlchemy query object

query, pagination = apply_pagination(query, page_number=1, page_size=10)

page_size, page_number, num_pages, total_results = pagination

assert 10 == len(query)
assert 10 == page_size == pagination.page_size
assert 1 == page_number == pagination.page_number
assert 3 == num_pages == pagination.num_pages
assert 22 == total_results == pagination.total_results

Filters format

Filters must be provided in a list and will be applied sequentially. Each filter will be a dictionary element in that list, using the following format:

filter_spec = [
    {'model': 'model_name', 'field': 'field_name', 'op': '==', 'value': 'field_value'},
    {'model': 'model_name', 'field': 'field_2_name', 'op': '!=', 'value': 'field_2_value'},
    # ...
]

The model key is optional if the original query being filtered only applies to one model.

If there is only one filter, the containing list may be omitted:

filter_spec = {'field': 'field_name', 'op': '==', 'value': 'field_value'}

Where field is the name of the field that will be filtered using the operator provided in op (optional, defaults to ==) and the provided value (optional, depending on the operator).

This is the list of operators that can be used:

  • is_null
  • is_not_null
  • ==, eq
  • !=, ne
  • >, gt
  • <, lt
  • >=, ge
  • <=, le
  • like
  • ilike
  • not_ilike
  • in
  • not_in
  • any
  • not_any

any / not_any

PostgreSQL specific operators allow to filter queries on columns of type ARRAY. Use any to filter if a value is present in an array and not_any if it's not.

Boolean Functions

and, or, and not functions can be used and nested within the filter specification:

filter_spec = [
    {
        'or': [
            {
                'and': [
                    {'field': 'field_name', 'op': '==', 'value': 'field_value'},
                    {'field': 'field_2_name', 'op': '!=', 'value': 'field_2_value'},
                ]
            },
            {
                'not': [
                    {'field': 'field_3_name', 'op': '==', 'value': 'field_3_value'}
                ]
            },
        ],
    }
]

Note: or and and must reference a list of at least one element. not must reference a list of exactly one element.

Sort format

Sort elements must be provided as dictionaries in a list and will be applied sequentially:

sort_spec = [
    {'model': 'Foo', 'field': 'name', 'direction': 'asc'},
    {'model': 'Bar', 'field': 'id', 'direction': 'desc'},
    # ...
]

Where field is the name of the field that will be sorted using the provided direction.

The model key is optional if the original query being sorted only applies to one model.

nullsfirst / nullslast

sort_spec = [
    {'model': 'Baz', 'field': 'count', 'direction': 'asc', 'nullsfirst': True},
    {'model': 'Qux', 'field': 'city', 'direction': 'desc', 'nullslast': True},
    # ...
]

nullsfirst is an optional attribute that will place NULL values first if set to True, according to the SQLAlchemy documentation.

nullslast is an optional attribute that will place NULL values last if set to True, according to the SQLAlchemy documentation.

If none of them are provided, then NULL values will be sorted according to the RDBMS being used. SQL defines that NULL values should be placed together when sorting, but it does not specify whether they should be placed first or last.

Even though both nullsfirst and nullslast are part of SQLAlchemy, they will raise an unexpected exception if the RDBMS that is being used does not support them.

At the moment they are supported by PostgreSQL, but they are not supported by SQLite and MySQL.

Running tests

The default configuration uses SQLite, MySQL (if the driver is installed, which is the case when tox is used) and PostgreSQL (if the driver is installed, which is the case when tox is used) to run the tests, with the following URIs:

sqlite+pysqlite:///test_sqlalchemy_filters.db
mysql+mysqlconnector://root:@localhost:3306/test_sqlalchemy_filters
postgresql+psycopg2://postgres:@localhost:5432/test_sqlalchemy_filters?client_encoding=utf8'

A test database will be created, used during the tests and destroyed afterwards for each RDBMS configured.

There are Makefile targets to run docker containers locally for both MySQL and PostgreSQL, using the default ports and configuration:

$ make mysql-container
$ make postgres-container

To run the tests locally:

$ # Create/activate a virtual environment
$ pip install tox
$ tox

There are some other Makefile targets that can be used to run the tests:

There are other Makefile targets to run the tests, but extra dependencies will have to be installed:

$ pip install -U --editable ".[dev,mysql,postgresql]"
$ # using default settings
$ make test
$ make coverage

$ # overriding DB parameters
$ ARGS='--mysql-test-db-uri mysql+mysqlconnector://root:@192.168.99.100:3340/test_sqlalchemy_filters' make test
$ ARGS='--sqlite-test-db-uri sqlite+pysqlite:///test_sqlalchemy_filters.db' make test

$ ARGS='--mysql-test-db-uri mysql+mysqlconnector://root:@192.168.99.100:3340/test_sqlalchemy_filters' make coverage
$ ARGS='--sqlite-test-db-uri sqlite+pysqlite:///test_sqlalchemy_filters.db' make coverage

Database management systems

The following RDBMS are supported (tested):

  • SQLite
  • MySQL
  • PostgreSQL

SQLAlchemy support

The following SQLAlchemy versions are supported: 1.0, 1.1, 1.2, 1.3, 1.4.

Changelog

Consult the CHANGELOG document for fixes and enhancements of each version.

License

Apache 2.0. See LICENSE for details.

sqlalchemy-filters's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sqlalchemy-filters's Issues

Filters excludes values if model name doesn't exists in filter_or

I have an issue, where my datamodel, sometimes have a relation to another table, and sometimes it is None. I use sqlalchemy-filters to search for items in a table, however when I add filter_or for a relation where the model name doesn't exists, all the items are excluded.

Is there any way I can avoid this behaviour? When i include some columns that only exists for some items/rows, even if try to search for another column, the items disappear because the column is included in the filter_or

In the below example, ProjectReference only exists for som items, where as other items have a relation to another table

filter_or=[
{"model": "ProjectReference", "field": "project_reference_name", "op": "ilike", "value": "%12345%"},
{"model": "SupplierPart", "field": "supplier_part_description", "op": "ilike", "value": "%12345%"},
{"model": "SupplierPart", "field": "part_inwatec_id", "op": "ilike", "value": "%12345%"},
{"model": "SupplierPart", "field": "supplier_part_id", "op": "ilike", "value": "%12345%"},
{"model": "Supplier", "field": "name", "op": "ilike", "value": "%12345%"}]

Error on applying filters on SQLAlchemy 1.4.0b1

I have encounterred following errors using
SQLAlchemy 1.4.0b1

query = apply_filters(query, sqla_filters)
File "/opt/venv/lib/python3.8/site-packages/sqlalchemy_filters/filters.py", line 235, in apply_filters
default_model = get_default_model(query)
File "/opt/venv/lib/python3.8/site-packages/sqlalchemy_filters/models.py", line 141, in get_default_model
query_models = get_query_models(query).values()
File "/opt/venv/lib/python3.8/site-packages/sqlalchemy_filters/models.py", line 64, in get_query_models
models.extend(mapper.class_ for mapper in query._join_entities)
AttributeError: 'Query' object has no attribute '_join_entities'

Python2 compatible

Hi,
I am trying to use this project on python2 and I get the following error,

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/lib/python2.7/site-packages/sqlalchemy_filters/__init__.py", line 3, in <module>
    from .filters import apply_filters  # noqa: F401
  File "/usr/lib/python2.7/site-packages/sqlalchemy_filters/filters.py", line 3, in <module>
    from inspect import signature
ImportError: cannot import name signature

deprecated import

DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working from collections import Iterable, namedtuple in filters.py

Operator JSON_CONTAINS

Hi, is it possible to add new Operator to support JSON_CONTAINS

'json_contains': lambda f, a: func.json_contains(
            f, func.json_array(a)
        ),

Thanks!

Groupby operations

Is there a way to do groupby operations?

I get this message:
TypeError: 'SortFilterQuery' object is not callable

need to call items to have them included ...

Hi,

I found something interesting. My db model has a few foreign relationships ... and I found that in the crud operation I need to "call" them, otherwise they're not included ... any ideas why this would be?

model:
`class Invoice(Base):

__tablename__ = "invoice"

id = Column(Integer, primary_key=True)
net_total = Column(Float(), nullable=False, server_default="0")
tax = Column(Float(), nullable=False, server_default="0")
total = Column(Float(), nullable=False, server_default="0")
invoice_num = Column(Integer)
year = Column(Integer, nullable=False, server_default=str(now.year))
# STATUSES: 1:open, 2:paid
status = Column(Integer, nullable=False, server_default="1")
invoice_date = Column(Date(), server_default=str(now))
invoice_due = Column(Date(), server_default=str(now))
service_rendered = Column(Date(), server_default=str(now))
created = Column(DateTime(), server_default=str(now))
updated = Column(DateTime(), server_onupdate=str(now))
description = Column(Unicode(255), server_default=f"Zaračunavamo vam ... ")

# foreign keys & relationships
company_id = Column(Integer(), ForeignKey("company.id"), nullable=False)
company = relationship("Company", back_populates="invoices")
partner_id = Column(Integer(), ForeignKey("partner.id"), nullable=False)
partner = relationship("Partner", back_populates="invoices")
items = relationship("InvoiceItems", back_populates="invoice")`

crud:

`
def get_invoices(db: Session, page: int = 1, limit: int = 100):

query = db.query(models.Invoice)

filter_spec = [{'field': 'status', 'op': '==', 'value': 2}]

filtered_query = apply_filters(query, filter_spec)

sort_spec = [
    {'model': 'Invoice', 'field': 'total', 'direction': 'desc'},
]

sorted_query = apply_sort(query, sort_spec)

paginated_query, pagination = apply_pagination(
    sorted_query, page_number=1, page_size=3)

query_result = paginated_query.all()

# for whatever magic you need to call children to be included?
for item in query_result:
    # just call them ...
    company = item.company
    partner = item.partner
    items = item.items
    # ... and do nothing.
    pass

result = {"rows": pagination.total_results,
          "pages": pagination.num_pages, "items": query_result}

return result`

Escape character for search string

Hello, please could we have a mechanism for defining an escape character for a search string, or alternatively have an escape chaacter such as \ predefined?

Many thanks

Next release

Hello,
I am in the process of evaluating this library for use in one of the projects we are working on. I see the last commit was over 9 months ago. Is this library being actively maintained? If so when is the next release?
Thank you
Sameer

project maintenance status and future roadmap

Hi @juliotrigo,

There has been some time since the sqlalchemy 1.4 release and the initial effort to bring the support for new version into this project. so far without response. Could you spend a few minutes to elaborate on your ability and willingness to continue a work on maintaining the project or sharing responsibilities for it's maintenance please ?

to all others using this project:

since I'm not a true python developer, I'm a little bit unsure about if me, or someone else might be willing to fork and continue to support this project. Also, according to the CI in github actions, there has been already some breaking changes in EOLed python3.5 code which magically prevents sqlalchemy to work properly so I wonder, if fork will take place should we try to keep so much backward compatibility or we'll be happy with just python >= 3.6 and sqlalchemy >= 1.3 ?

any ideas are welcome

apply_filters with an optional OR argument

Hello,

In my application I really need an apply_filters OR edition
I have made a custom function for this, but would there be an interest in a PR to include this in the regular apply_filters? backwards compatible by an optional argument called "as_or" or similar?

Filter joined table

Hola Julio, primero que nada muchas gracias por el package, estoy creando una Api Rest con flask y me está siendo super util.
Te queria consultar un problema que estoy teniendo al filtrar un modelo relacionado a otro modelo, es una relación de uno a muchos que tengo entre pacientes y consultas, y quiero obtener, por ejemplo, un paciente con todas sus consultas menos una (que seria la del id 11) pero no está funcionando, solo funciona el filtro en el modelo Paciente:

def get_paciente_filtering_consultas(id):
    query = db.session.query(Paciente)
    filter_spec = [
        {'model': 'Paciente', 'field': 'id', 'op': '==', 'value': id},
        {'model': 'PacienteConsulta', 'field': 'id', 'op': '!=', 'value': 11},
    ]
    filtered_query = apply_filters(query, filter_spec)
    return filtered_query.first()

la relación en el modelo Paciente está definida de la siguiente forma:

class Paciente(db.Model):
    """ Paciente Model """
    __tablename__ = "paciente"
    consultas = db.relationship('PacienteConsulta', lazy='joined',order_by="desc(PacienteConsulta.created_at)")

El filtro del id es solo de prueba, en realidad mi idea es filtrar consultas por fecha, pero al probar esto me di cuenta que tampoco funcionaba.

Muchas gracias!

document code Pagination sort order error:

in pagination.py:

def apply_pagination(...)
...

return query, Pagination(page_number, page_size, num_pages, total_results)

image

in the document:

page_size, page_number, num_pages, total_results = pagination

image

it will cause page_size became page_number and page_number became page_size

Filtering with comparisons between fields

Hi all,

I am just wondering if the functionality for filtering with comparisons between fields is available through "apply_filters"?

e.g. if field_1 > field_2

I have tried { "model" : "Foo", "field": "field_1", "op":">", "field": "field_2" } however the filter requires a "value".

Field value type validation

Currently there is no type validation.

If the following query is ran against the example models SQLAlchemy will raise a StatementError exception.

{'field': 'count', 'op': '==', 'value': 'not an int'}
class Base(object):
    id = Column(Integer, primary_key=True)
    name = Column(String(50), nullable=False)
    count = Column(Integer, nullable=True)


Base = declarative_base(cls=Base)


class Foo(Base):

    __tablename__ = 'foo'

It would be useful to validate the value against the model's field type before the query is executed. This would allow the proper HTTP error to be given to a REST API user.

It probably would make sense to use the same conversion mechanism that is already used in SQLAlchemy so custom types can be validated as well.

filter on DateTime and Time sqlalchemy column types

Hello!

I'm currently using this library but it seems like I'm not able to use operators gt and eq on sqlalchemy's Time column type.

I guess it is comparing using the value string representation of the information.. am I right? Is there a way to override the comparator for a particular column or at least override it globally?

Thank you

Possible to pass value to hybrid_method?

I've got a related model that provides a key/value extension of the main model and I'd like to be able to sort on the related model key/value. So, I want to say, "sort on the value field, if the key matches foo". I thought maybe I could use a hybrid method and pass the key to the method as shown below. I don't see anyway to pass that value to the hybrid method. I get the way the API is made, is there another way to accomplish this? If not, is can we add maybe an optional kwargs to the sort_spec that gets expanded if the sort field has the __call__ attribute? Another approach is maybe a sort of subquery?

class ImageProperty(db.Model):
    __tablename__ = "image_properties"

    id: Mapped[int] = mapped_column(primary_key=True)
    image_id: Mapped[str] = mapped_column(ForeignKey("images.id"))
    key: Mapped[str]
    value: Mapped[str]

    def __init__(self, key: str, value: str):
        self.key = key
        self.value = value

    @hybrid_method
    def value_for_key(self, key: str) -> str | None:
        if self.key == key:
            return self.value
        else:
            return None

class Image(ProxiedDictMixin, db.Model):
    __tablename__ = "images"

    id: Mapped[str] = db.Column(db.String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    properties: Mapped[dict[str, "ImageProperty"]] = relationship(
        collection_class=attribute_keyed_dict("key"), cascade="all, delete-orphan"
    )

Snippet to sort

if hasattr(Image, key):
    logger.debug("%s", {"model": "Image", "field": key, "direction": dir})
    sort_spec.append({"model": "Image", "field": key, "direction": dir})
else:
    logger.debug("%s", {"model": "ImageProperty", "field": key, "direction": dir})
    # TODO(dcode): This isn't right. need to sort on value when key == key
    sort_spec.append({"model": "ImageProperty", "field": value_for_key, "direction": dir})

JSON fields

Is it possible to support the filtering function by the key values of JSON fields?
SQLAlchemy has a JSON_EXTRACT function and I can filter Model.json_column ['key'] == value

Issue with sorting when query contains a column which is generated using Count method

When using the Sorting function and query contains a column generated using the count column.
Error is in below function at models.get_query_models.
`
def get_query_models(query):
"""Get models from query.

:param query:
    A :class:`sqlalchemy.orm.Query` instance.

:returns:
    A dictionary with all the models included in the query.
"""
models = [col_desc['entity'] for col_desc in query.column_descriptions]

`

Here for such column models contain a None element.

I am proposing a solution where we can remove the None value from the list.

'contains' operator

Please add the sqlachemy operator "contains" to the OPERATORS dictionary:
'contains': lambda f, a: f.contains(a),

Thank you!

Datetime comparison not working?

Hi,

I've been successfully using this excellent tool for a few months and this is the very first time I find myself in need of using datetime-based filters.

I'm trying to apply a range but the resulting query doesn't seem to be what I was expecting.

The filter itself looks like:
[{'model': 'Job', 'field': 'dueDate', 'operator': 'gt', 'value': datetime.datetime(2008, 6, 1, 0, 0)}]

Which is later on rendered as:

WHERE job."dueDate" = %(dueDate_1)s

So, the filter is somewhat applied, but with the wrong operator.

I'm open to provide extended data if required.

Thanks a lot for your help.

Cheers,
Javier

Type casting support in filters

When attempting to filter on the id of a model with UUID as the type, I receive the error:

psycopg2.errors.UndefinedFunction: operator does not exist: uuid ~~* unknown
LINE 3: ...a-556b4fc5b33c'::uuid AND my_table.id ILIKE '123...

Could we, perhaps, supply a cast value in the filter entry, or, even better, dynamically detect the type of the column and provide the coercion, as done in SqlAlchemy Coercion

Providing an explicit type cast as:

filters = [{'field': 'id', 'op': 'ilike', 'value': '123%', 'cast': 'uuid'}]

...to generate the SQL:

WHERE my_table.id ILIKE '123%'::uuid

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.