1. Introducción
Hola a todos y bienvenidos a un nuevo post de de nuestro querido blog!. En el post anterior vimos como crear filtros complejos a través de graphene-sqlalchemy-filter
. Hicimos búsquedas de subtextos haciendo uso del operador like
. Sin embargo éste solo puede ser aplicado a atributos de tipo String
. En este post definiremos un nuevo filtro, que hemos llamado likeall
, que nos permitirá hacer búsquedas de tipo like con independencia del tipo del atributo que se esté considerando.
Es necesario echarle un vistazo al post anterior ya que éste es una continuación del mismo y únicamente mostraremos los elementos nuevos para crear el operador likeall
.
Tecnologías empleadas:
- Python 3.6
- Flask 1.1.1
- Graphene 2.1.8
- Graphene SQLAlchemy Filter 1.10.2
- SQLAlchemy 1.3.13
- SQLite
Os podéis descargar el código de mi GitHub que se encuentra aquí.
2. Fuentes
Extendemos la clase FilterSet
del fichero filter.py
definiendo el nuevo operador a través del atributo EXTRA_EXPRESSIONS. La función a ejecutar se establece a través del atributo filter
. En este caso definimos la función likeall_filter
que recibirá por parámetro el atributo field que representa una instancia de la clase Field
de SQLAlchemy
y el valor a aplicar.
... def likeall_filter(field, value: str): return func.lower(func.cast(field, String)).like('%' + str(value).lower() + '%') class MyFilterSet(FilterSet): LIKEALL = 'likeall' EXTRA_EXPRESSIONS = { 'likeall': { 'graphql_name': 'likeall', 'for_types': [types.Date, types.DateTime, types.String, types.Int, types.Decimal], 'filter': likeall_filter, 'input_type': ( lambda type_, nullable, doc: graphene.String(nullable=False) ), 'description': 'Filter like for all types', } } class Meta: abstract = True class UserFilter(MyFilterSet): ...
El resto de ficheros permanecen igual que en el post anterior.
3. Testeando la aplicación
Uilizamos unittest
. Definimos dos filtros de prueba. Uno para filtrar por el campo alfanumérico name y otro para consultar por el campo numérico age.
... FILTER_LIKE_ALL_STRING = """ query{ user(filters: {nameLikeall: "Jo"}){ edges{ node{ userid name surname age } } } } """ FILTER_LIKE_ALL_NUMBER = """ query{ user(filters: {ageLikeall: "3"}){ edges{ node{ userid name surname age } } } } """ ...
Definición de los tests
... class UserTest(unittest.TestCase): ... def test_should_validate_like_all_operator(self): self.assertEqual( {"data": {"user": {"edges": [{"node": {"userid": "1", "name": "Jorge", "surname": "Hernandez", "age": 32}}, {"node": {"userid": "2", "name": "Jose", "surname": "Hernandez", "age": 32}}]}}}, self.client.execute(self.FILTER_LIKE_ALL_STRING)) def test_should_validate_like_all_operator(self): self.assertEqual( {"data": {"user": {"edges": [{"node": {"userid": "1", "name": "Jorge", "surname": "Hernandez", "age": 32}}, {"node": {"userid": "2", "name": "Jose", "surname": "Hernandez", "age": 32}}]}}}, self.client.execute(self.FILTER_LIKE_ALL_NUMBER))