从查询集删除列

时间:2019-05-21 23:53:19

标签: python django ply

我不确定这是一个问题还是对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])

实施将其包含在列表中的测试(我使用的是全局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函数。

如果我不删除该列,则在解析器满足“与”或“或”运算时,就会出现错误django.db.utils.OperationalError: SELECTs to the left and right of INTERSECT do not have the same number of result columns

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

0 个答案:

没有答案