我正在为Django和DjangoRestFramework编写一个Web应用程序,用于我学校的内部应用程序。它是用Microsoft Access 2003编写的一个非常古老的本土应用程序的替代品。我的用户非常希望拥有的功能之一是能够搜索字段(例如donation_amount
donation
} table)不仅有确切的数量,而且有一个如下的查询:
< 130 and > 125
Access目前允许这种功能,它非常有用,但我完全没有意识到如何实现这样的方法而不将其查询直接插入SQL(非常危险)或在Python中使用eval
表达(甚至更危险)。
是否有允许这样做的图书馆或子语言?
答案 0 :(得分:1)
我不熟悉Django的生态系统,但Python标准库包含ast.parse
,它解析有效的Python表达式字符串并生成一个抽象语法树,您可以将其解析并转换为查询 - 或者功能调用系列,或任何你需要的系列。因此,如果您找不到更具体的内容,那么这可能会有用。
此代码:
ast.parse('donation_amount < 130 and donation_amount > 125')
返回以下AST结构:
ast.Module(
ast.Expr([
ast.BoolOp(ast.And(), [
ast.Compare(
[ast.Lt()],
ast.Name('donation_amount', ast.Load()),
[ast.Num(130)]),
ast.Compare(
[ast.Gt()],
ast.Name('donation_amount', ast.Load()),
[ast.Num(125)])])]))
因此,它会处理解析,但您仍需要将其转换为您自己的查询。但看起来您只需要处理少量节点类型:
BoolOp -> and, or
Compare -> ==, !=, >, <, >=, <=, in, not in
Name -> identifiers (column names, true/false/null, etc.)
Num -> numbers
Str -> strings
如果要支持数据库功能,可能还有ast.Call
个节点,如果要支持ast.Tuple
功能,还需要ast.List
或IN
个节点。如果AST包含任何其他节点类型,则可以将其拒绝为无效查询。
答案 1 :(得分:0)
您是否使用Django ORM来建模数据库?如果是这样,那就不会归结为:
Donation.objects.filter(donation_amount__lte=130).filter(donation_amount__gte=125)