Mat*_*kic 1 python flask-sqlalchemy
我正在尝试使用 Flask-sqlalchemy 查询动态创建 order_by 语句。
这是对我的 PurchaseOrder 方法的调用:
pos = PurchaseOrder.get_all_pos(column_order=['id', 'due_date'])
Run Code Online (Sandbox Code Playgroud)
column_order 可以有一个或多个列,我们用来对查询结果进行排序。
class PurchaseOrder(PurchaseOrderDB):
@classmethod
def get_all_pos(cls, **kwargs):
columns = kwargs.pop('column_order', '')
columns_order = [getattr(cls, column) for column in columns]
if len(columns_order) != 0:
pos = cls.query.order_by(columns_order).all()
else:
pos = cls.query.all()
return pos
Run Code Online (Sandbox Code Playgroud)
columns_order 是 InstrumentedAttributes 的列表,当我将该列表传递给 order_by() 方法时,我得到了预期的以下错误:
sqlalchemy.exc.ArgumentError: SQL expression object or string expected, got object of type <class 'list'> instead
Run Code Online (Sandbox Code Playgroud)
那么,当我们不知道传入多少列时,是否有其他方法可以动态创建 order_by 呢?在这种情况下,查询应如下所示:
pos = cls.query.order_by(cls.id, cls.due_date).all()
Run Code Online (Sandbox Code Playgroud)
我已经使用 text() 方法解决了这个问题(如@shmee 在上述问题的评论中指出的那样)。
我更改了作为 column_order 传递的参数类型(现在它是一个字符串)
pos = PurchaseOrder.get_all_pos(column_order='id, due_date')
Run Code Online (Sandbox Code Playgroud)
您还可以在每个列名称之后对每列使用 asc 或 desc(升序或降序)顺序:
pos = PurchaseOrder.get_all_pos(column_order='id desc, due_date asc')
Run Code Online (Sandbox Code Playgroud)
我还对我的方法进行了一些重构,所以现在它工作正常。
class PurchaseOrder(PurchaseOrderDB):
@classmethod
def get_all_pos(cls, **kwargs):
columns_order = kwargs.pop('columns_order', '')
if columns_order:
return cls.query.order_by(text(columns_order)).all()
else:
return cls.query.all()
Run Code Online (Sandbox Code Playgroud)
这是 text() 文档: https://docs.sqlalchemy.org/en/13/core/sqlelement.html#sqlalchemy.sql.expression.text
此外,text() 的 text.text 参数可以作为 Python 字符串参数传递,该参数将被视为可信 SQL 文本并按给定方式呈现。请勿将不受信任的输入传递给此参数。
这意味着您必须仅传递受信任的 SQL 字符串。在我的情况下,我只传递硬编码字符串。例如,如果您使用来自应用程序用户的字符串,则该字符串可能包含一些不需要的 SQL 注入。
因此,请始终验证用户定义的字符串。
| 归档时间: |
|
| 查看次数: |
2976 次 |
| 最近记录: |