Flask - 将 request.args 转换为字典

11

我一直在尝试弄清楚如何将request.args传递给sqlalchemy过滤器。

我认为这应该可以工作:

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

但它抛出了错误:

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

当userid或其他get参数存在时。

根据这篇文章 - https://dev59.com/CmIk5IYBdhLWcg3wMLiI - 您可以将一个字典传递给过滤器函数。

有什么想法我做错了什么吗?

非常感谢 :)

更新:非常感谢下面的发帖者,但现在它报以下错误:

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'],)

有什么想法吗?

4个回答

19

首先,您必须使用 filter_by 而不是 filter

其次,Flask 的 request.args 使用 MultiDict,这是一个包含值列表的字典,允许同一键具有多个值,因为在查询字符串中相同的字段可能会出现多次。 您收到错误是因为 SQL 查询得到了 [u'41'],但它仅期望 '41'。 您可以使用 request.args.to_dict() 来解决:

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

4
这是正确的答案。另外补充一点:使用request.args.to_dict()是正确的做法,而dict(request.args)则不正确,因为它会生成一个值由列表组成的字典。 - Red-Tune-84

4

使用filter_by

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

filter 的使用方法如下:query.filter(Class.property == value),而 filter_by 的使用方法如下:query.filter_by(property=value) (前者是一个表达式,后者是一个关键字参数)。


2
如果您有非模型查询参数,例如用于分页的page,那么使用filter_by(**request.args)可能会出现问题,否则您将会得到类似以下的错误信息:
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) (如果您使用此节省样板的模块,可以免费获取上述代码片段)

1

You can:

http://localhost:5000/filter-test?var=test

query_dict = request.args.to_dict()

print(query_dict)
{'var': 'test'}

print(query_dict['var'])
var


尽管这段代码可能解决了问题,但包括解释它如何以及为什么解决了问题将有助于提高您的帖子质量,可能会导致更多的赞同。请记住,您正在为未来的读者回答问题,而不仅仅是现在提问的人。请[编辑]您的答案以添加解释,并指出适用的限制和假设。 - Yunnosch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接