Передача пустых параметров в качестве условия фильтра в запросе flask sqlalchemy get

#python #flask #sqlalchemy #flask-sqlalchemy #flask-restful

#python #flask #sql — алхимия #колба-sqlalchemy #flask-restful

Вопрос:

Сценарий

Я создаю GET API, который должен принимать параметры, применять фильтры и возвращать результат.

Технический стек: flask-restful (фреймворк), flask-sqlalchemy (orm), MySQL (база данных)

Предположим, у меня есть четыре параметра в моем GET запросе, а именно, p1, p2, p3, p4 и соответствующие значения равны v1, v2, v3, v4 . Любой или все параметры МОГУТ ИМЕТЬ НУЛЕВОЕ ЗНАЧЕНИЕ.

Пример: это http://myhost.com/apply-filter?p1=v1amp;p3=v4 допустимый запрос для нашего случая.

Предположим, что те же поля (столбцы) присутствуют и в таблице базы данных.
Имя модели Model

В чем не проблема

API должен применять and условие для всех этих параметров и возвращать все строки, которые удовлетворяют этим параметрам. Я немного разбираюсь в flask и sqlalchemy, поэтому сначала я сделал что-то вроде этого:

 db.session.query(Model).filter(Model.p1 == v1, Model.p2 == v2, Model.p3 == v3, Model.p4 == v4).all()
 

Работает нормально…

Проблема

Теперь проблема в том, что я не могу понять, что делать, если пользовательский запрос не имеет значений для одного или нескольких параметров, т. Е. Что, Если он / она хочет фильтровать только по p1 и p3?

Я знаю, что могу решить эту проблему, используя if...else , но есть ли лучший способ?

Что-то вроде:

 db.session.query(Model).filter(Model.p1 == v1 or all, Model.p2 == v2 or all, Model.p3 == v3 or all, Model.p4 == v4 or all)
 

Метод запроса: GET
Предположим, только одна таблица.
Извлечение параметров с помощью request.args.get('param')

Намасте🙏

Ответ №1:

Метод 1 (серверная часть)

Вы можете сделать это более элегантным способом, чем if...else , но не обязательно проще. Предположим, что это ваш URL-адрес запроса:

 http://myhost.com/apply-filter?p1=v1amp;p2=amp;p3=v3
 

Как вы можете видеть, значение p2 пустое. Сначала вам нужно будет получить словарь аргументов / значений.

 args = request.args #args = {"p1": v1, "p2": None, "p3": v3}
 

Далее вам нужно будет отфильтровать этот словарь, чтобы удалить элементы, имеющие значение None.

 filtered_args = {k: v for k, v in args.items() if v is not None} #filtered_args = {"p1": v1, "p3": v3}
 

Вам также нужно будет создать расходный фильтр Sqlalchelmy (BinaryExpression):

 filters = [getattr(Model, attribute) == value for attribute, value in filtered_args.items()]
 

Наконец, вы можете выполнить свой запрос, используя соединение and_:

 db.session.query(Model).filter(and_(*filters)).all()
 

Метод 2 (интерфейс)

Вы также можете отфильтровать запрос во внешнем интерфейсе перед отправкой запроса api. Это можно сделать, изначально не включая параметры с пустыми значениями. В противном случае вам придется использовать некоторый базовый код Javascript для удаления ненужных параметров (источник)

 let url = new URL('https://example.com?foo=1amp;bar=2amp;foo=3');
let params = new URLSearchParams(url.search);

// Delete the foo parameter.
params.delete('foo'); //Query string is now: 'bar=2'