【问题标题】:Search criteria language parser in Python?Python中的搜索条件语言解析器?
【发布时间】:2014-11-19 20:28:29
【问题描述】:

我正在使用 Django 和 DjangoRestFramework 为我学校的内部应用程序编写一个网络应用程序。它是一个用 Microsoft Access 2003 编写的非常古老的本土应用程序的替代品。我的用户非常希望拥有的功能之一是能够搜索一个字段(例如 donationtable 中的 donation_amount)而不是仅按确切金额,但使用如下查询:

< 130 and > 125

Access 目前允许这种功能,它非常有用,但是我完全不知道有一种方法可以在不将查询直接插入 SQL(非常危险)或在 Python 表达式中使用 eval(更危险)。

是否有任何库或子语言允许这样做?

【问题讨论】:

    标签: python django parsing django-rest-framework


    【解决方案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 节点,如果您想支持IN 功能,则可能是ast.Tupleast.List 节点。如果 AST 包含任何其他节点类型,您可以将其作为无效查询拒绝。

    【讨论】:

      【解决方案2】:

      您是否使用 Django ORM 对数据库进行建模?如果是这样,那么它不会归结为:

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

      【讨论】:

      • 你说的完全正确,就是这么简单。但是,问题是如何(安全地)将字符串解析为我可以在代码中识别的内容,然后转换为您显示的 Django 代码。
      猜你喜欢
      • 1970-01-01
      • 2012-03-14
      • 2017-03-03
      • 1970-01-01
      • 2021-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-31
      相关资源
      最近更新 更多