Flask — преобразовать request.args в dict

Я пытался понять, как передать request.args фильтру sqlalchemy.

Я думал, что это должно работать:

model.query.filter(**request.args).all()

Но выдает ошибку:

TypeError: <lambda>() got an unexpected keyword argument 'userid'

Когда присутствует идентификатор пользователя или любой другой аргумент получения.

Согласно этому сообщению - https://stackoverflow.com/questions/19506105/flask-sqlalchemy-query-with-keyword-as-variable - вы можете передать dict к функции фильтра.

Любые идеи, что я делаю неправильно?

Большое спасибо :)

ОБНОВЛЕНИЕ: большое спасибо плакату ниже, однако теперь он выдает следующую ошибку:

ProgrammingError: (ProgrammingError) (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') ORDER BY tblclients.clientname' at line 3") 'SELECT favourites.id AS favourites_id, favourites.userid AS favourites_userid, favourites.clientid AS favourites_clientid, favourites.last_visit AS favourites_last_visit \nFROM favourites INNER JOIN tblclients ON tblclients.clientid = favourites.clientid \nWHERE favourites.userid = %s ORDER BY tblclients.clientname' ([u'41'],)

Есть идеи?


person Ben Kilah    schedule 30.10.2013    source источник


Ответы (3)


Во-первых, вы должны использовать filter_by, а не filter.

Во-вторых, Flask request.args использует MultiDict, словарь со значениями внутри списка, допускающий более одного значения для одного и того же ключа, поскольку одно и то же поле может появляться в строке запроса более одного раза. Вы получили ошибку, потому что SQL-запрос получил [u'41'], хотя ожидал только '41'. Вы можете использовать request.args.to_dict(), чтобы исправить это:

model.query.filter_by(**request.args.to_dict()).all()
person Pedro Werneck    schedule 01.11.2013
comment
Это правильный ответ. И добавить к этому: использование request.args.to_dict() является правильным, а dict(request.args) - нет, потому что он создаст словарь, значения которого состоят из списков. - person Red-Tune-84; 18.05.2017

Используйте 1_:

model.query.filter_by(**request.args).all()

filter используется так: query.filter(Class.property == value), а filter_by используется так: query.filter_by(property=value) (первое из них является выражением, а второе — аргументом ключевого слова).

person javex    schedule 30.10.2013

filter_by(**request.args) не работает, если у вас есть немодельные параметры запроса, такие как page для разбиения на страницы, иначе вы получите такие ошибки:

InvalidRequestError: Entity '<class 'flask_sqlalchemy.JobSerializable'>' has no property 'page'

Я использую что-то вроде этого, которое игнорирует параметры запроса не в модели:

    builder = MyModel.query
    for key in request.args:
        if hasattr(MyModel, key):
            vals = request.args.getlist(key) # one or many
            builder = builder.filter(getattr(MyModel, key).in_(vals))
    if not 'page' in request.args:
        resources = builder.all()
    else:
        resources = builder.paginate(
            int(request.args['page'])).items

Учитывая модель со столбцом с именем valid, будет работать что-то вроде этого:

curl -XGET "http://0.0.0.0/mymodel_endpoint?page=1&valid=2&invalid=whatever&valid=1"

invalid будет проигнорирован, а page доступен для разбиения на страницы и, что самое приятное, будет сгенерирован следующий SQL: WHERE mymodel.valid in (1,2)

(получите приведенный выше фрагмент бесплатно, если используете этот модуль сохранения шаблонов )

person opyate    schedule 02.01.2015