#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'