首页 > 解决方案 > 从查询集中删除一列

问题描述

我不太确定这是一个问题,还是对 Django 的功能请求,或者我让事情变得不必要的复杂。我正在编写一个用户界面,让用户编写查询,我将其转换为 Django 查询集的创建、修改和组合。

该软件使用ply, (写入p[0]等于return),这里有一些语法摘录:

在这里,我将看起来像单词或用点分隔的单词转换为 django 可以识别的东西。

def p_field_fieldname(p):
    'field : fieldname'
    p[0] = p[1]

def p_field_dot_fieldname(p):
    'field : field DOT fieldname'
    p[0] = '{}__{}'.format(p[1], p[3])

实现包含在列表中的测试(我正在使用 global search_domain,这显然会造成麻烦,但这不是重点)。

def p_bfactor_list_comprehension(p):
    'bfactor : field IN LBRACKET valuelist RBRACKET'
    p[0] = search_domain.objects.filter(**{'{}__in'.format(p[1]): p[4]})

组合bfactor令牌。

def p_bterm_bfactor(p):
    'bterm : bfactor'
    p[0] = p[1]

def p_expression_or_bterm(p):
    'expression : expression OR bterm'
    p[0] = p[1].union(p[3])

def p_bterm_and_bfactor(p):
    'bterm : bterm AND bfactor'
    p[0] = p[1].intersection(p[3])

到目前为止,一切都很好。我遇到的问题是当我引入聚合函数时,结合其他查询,让用户编写如下内容:

taxon where rank.id>=17 and count(verifications)=0

我正在实现count,我通过添加一个额外的列并对其进行测试来做到这一点,但是我一直很难尝试将两个查询集、两个子句的结果count(verifications)=0rank.id>=17.

我试过了,但在使用defer我没有设法删除该列。

最后,我写了这个非常丑陋的解决方案,

def p_bfactor_aggregate_comparison(p):
    'bfactor : aggregate LPAREN field RPAREN operator value'
    from django.db.models import Count, Sum  # adding field to qs
    _, aggregate, _, field, _, operator, value = p
    f = {'count': Count, 'sum': Sum}[aggregate]
    q = search_domain.objects.annotate(temp_field=f(field))
    matching = set(i['id'] 
        for i in q.filter(**{'temp_field__{}'.format(operator): value})
                  .values('id'))
    p[0] = search_domain.objects.filter(id__in=matching)

我的另一个最佳猜测(更准确地说,我希望它会起作用)是:

def p_bfactor_aggregate_comparison(p):
    'bfactor : aggregate LPAREN field RPAREN operator value'
    from django.db.models import Count, Sum  # adding field to qs
    _, aggregate, _, field, _, operator, value = p
    f = {'count': Count, 'sum': Sum}[aggregate]
    q = search_domain.objects.annotate(temp_field=f(field))
    p[0] = q.filter(**{'temp_field__{}'.format(operator): value}
        ).WHATEVERWORKS('temp_field')

然而不幸的是,我没有找到该WHATEVERWORKS功能。

如果我不删除该列,一旦解析器遇到 AND 或 OR 产品,它就会给出错误django.db.utils.OperationalError: SELECTs to the left and right of INTERSECT do not have the same number of result columns

从 2012 年到今年年初,我一直在使用 SQLAlchemy,在那里我已经实现了与此非常相似的东西。使用 Django,我得到的印象是我落后于一个过于聪明的抽象层。

标签: pythondjangoply

解决方案


推荐阅读