动态地进行查询

时间:2017-09-04 14:55:30

标签: python django postgresql

我正在努力寻找动态制作查询的最佳方法。 项目的前端会将json发送到后端,以通过查询参数查询对象:

Model.objects.filter(**query)

我可以根据自己的意愿设置json格式。在这一刻json:

# first case
{'type': 'channel_type', 'or': {'param1': {'__gte': 10}, 'param2': {'': 12}}}
# second case
{'type': {'in': ['channel1', 'channel2']}, 'and': {'p1': {'__lte': 12}, 'p2': {'!=': 1}}}

这在sql中是相同的(从y中选择x - 将是静态的,代码只生成'其中'条件):

# first case
WHERE table.type = channel_type AND (table.param1 >= 10 OR table.param2 = 12)
# second case
WHERE table.type IN [channel1, channel2] AND (table.p1 <= 12 AND table.p2 <> 1)

我已经这样做了:

query_params_dict = {'>': '__gt', '<': '__lt', '>=': '__gte', '<=': '__lte', '==': ''}

def parse_segmentation_query(query):
    type = {'type': query.pop('type')} if isinstance(query['type'], str) else {'type__in': query.pop('type')['in']}
    query = recursive_parsing_query(query)
    query.update(type)
    return query

Func&#34; recursive_parsing_query&#34;没准备好,所以没有显示。 但是我希望从dict中递归弹出params并使{&#39; param1__gte&#39;:2} dict将传递给** kwards for objects.filter。 麻烦正在变得不平等&#34; condition =&gt;它打破了简单的&#34; Model.objects.filter(**查询),因为我们需要&#34;排除&#34;。

我想知道:这种方式最适合动态制作查询吗?或者你可以提供更好的?如果没有,那么如何通过仅过滤条件传递排除?

UPD: 肯定json-query会更深入

更新:

最后,我这样做了(通过数字字段过滤进行动态查询),感谢MJafar Mash:

condition_types = {'>': '__gt', '<': '__lt', '>=': '__gte', '<=': '__lte', '==': '', '!=': ''}
q_conditions = {'or': True, 'and': False}


def recursive_parsing_query(query, or_condition=False):
    filter_obj = Q()
    for key, value in query.items():
        if key in q_conditions:
            local_filter = recursive_parsing_query(value, q_conditions[key])
        else:
            local_filter = simple_parsing_query(key, value)
        if or_condition:
            filter_obj |= local_filter
        else:
            filter_obj &= local_filter
    return filter_obj


def simple_parsing_query(parameter_name, parameter_query):
    local_filter = Q()
    for condition_type, condition_value in parameter_query.items():
        parameter_condition = {parameter_name + condition_types[condition_type]: condition_value}
        if condition_type != '!=':
            local_filter = Q(**parameter_condition)
        else:
            local_filter = ~Q(**parameter_condition)
    return local_filter

1 个答案:

答案 0 :(得分:2)

filterexclude internally implemented方式的启发,我建议重写您的查询生成算法以使用Q objects然后我想你赢了' t对查询生成算法的否定或递归有任何问题。