Python中的搜索条件语言解析器?

2024-05-20 00:05:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用Django和DjangoRestFramework为我学校的内部应用程序编写一个web应用程序。它是微软access2003中一个非常古老的国产应用程序的替代品。我的用户非常希望拥有的功能之一是能够搜索一个字段(例如donation_amountdonation表中),不仅可以搜索确切的数量,还可以使用如下查询:

< 130 and > 125

Access目前允许这种功能,而且非常有用,但是我完全不知道有什么方法可以实现这样的功能,而不直接将查询插入SQL(非常危险)或在Python表达式中使用eval(甚至更危险)。你知道吗

有没有允许这样做的库或子语言?你知道吗


Tags: anddjango用户功能web应用程序替代品数量
2条回答

我不熟悉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节点;如果您想支持IN功能,可以使用ast.Tupleast.List节点。如果AST包含任何其他节点类型,则可以将其作为无效查询拒绝。你知道吗

您是否使用Django ORM对数据库进行建模?如果是这样的话,那就不能归结为:

 Donation.objects.filter(donation_amount__lte=130).filter(donation_amount__gte=125)

相关问题 更多 >