在Python中搜索标准语言解析器?

时间:2014-11-19 10:03:19

标签: python django parsing django-rest-framework

我正在为Django和DjangoRestFramework编写一个Web应用程序,用于我学校的内部应用程序。它是用Microsoft Access 2003编写的一个非常古老的本土应用程序的替代品。我的用户非常希望拥有的功能之一是能够搜索字段(例如donation_amount donation } table)不仅有确切的数量,而且有一个如下的查询:

< 130 and > 125

Access目前允许这种功能,它非常有用,但我完全没有意识到如何实现这样的方法而不将其查询直接插入SQL(非常危险)或在Python中使用eval表达(甚至更危险)。

是否有允许这样做的图书馆或子语言?

2 个答案:

答案 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.ListIN个节点。如果AST包含任何其他节点类型,则可以将其拒绝为无效查询。

答案 1 :(得分:0)

您是否使用Django ORM来建模数据库?如果是这样,那就不会归结为:

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