基于 kendo UI 过滤器动态构建 Django 查询

Build Django Query Dynamically based on kendo UI filter

我正在尝试根据用户过滤器查询数据库。我从 kendo UI 网格收到以下输入。

{
   "filter":{
      "filters":[
         {
            "logic":"or",
            "filters":[
               {
                  "field":"aging",
                  "operator":"eq",
                  "value":24
               },
               {
                  "field":"aging",
                  "operator":"eq",
                  "value":13
               }
            ]
         },
         {
            "logic":"or",
            "filters":[
               {
                  "field":"follow_up_name",
                  "operator":"eq",
                  "value":"Call Insurance Provider"
               }
            ]
         },
         {
            "logic":"or",
            "filters":[
               {
                  "field":"patient_name",
                  "operator":"eq",
                  "value":"kartik"
               }
            ]
         },
         {
            "logic":"and",
            "filters":[
               {
                  "field":"created_date",
                  "operator":"eq",
                  "value":"2022-01-09T18:30:00.000Z"
               },
               {
                  "field":"created_date",
                  "operator":"gte",
                  "value":"2022-01-04T18:30:00.000Z"
               }
            ]
         },
         {
            "logic":"or",
            "filters":[
               {
                  "field":"follow_up_status",
                  "operator":"eq",
                  "value":"Open"
               }
            ]
         },
         {
            "logic":"or",
            "filters":[
               {
                  "field":"role_name",
                  "operator":"eq",
                  "value":"Pharmacist"
               }
            ]
         },
         {
            "logic":"or",
            "filters":[
               {
                  "field":"last_response",
                  "operator":"eq",
                  "value":"To-Patient"
               }
            ]
         }
      ],
      "logic":"and"
   },
   "skip":0,
   "take":10
}

根据以上数据,我需要 'and' 和 'or' 条件来动态构建查询。并将其传递给数据库。过滤器也可以包含多个列表。还想让这些 class 通用,它只能采用 UI 个参数构建查询和 return。请提供解决方案。

Q对象是你的朋友。

from django.db.models import QuerySet, Q
from functools import reduce

def filter_rec(data: dict) -> Q:
    logic = data.get('logic', None)
    # Leaf node
    if logic is None:
        field = data['field']
        operator = data['operator']
        value = data['value']
        return Q(**{f'{field}__{operator}': value})
    # Node with children
    children = list()
    for item in data['filters']:
        child = filter_rec(child)
        children.append(child)
    if logic == 'and':
        query = reduce(lambda x, y: x & y, children)
    elif logic == 'or':
        query = reduce(lambda x, y: x | y, children)
    return query

def kendo_filter(data: dict, qs: QuerySet) -> QuerySet:
    query = filter_rec(data['filter'])
    skip = data['skip']
    take = data['take']
    filtered_qs = qs.filter(query)
    paginated_qs = filtered_qs[skip:skip+take]
    return paginated_qs

总的要点是这样的。由您来验证数据并进行错误处理。

filter_rec(data['filter']) returns 以下为您的示例数据:

 <Q: (
    AND: 
        (OR: ('aging__eq', 24), ('aging__eq', 13)), 
        ('follow_up_name__eq', 'Call Insurance Provider'), 
        ('patient_name__eq', 'kartik'), 
        ('created_date__eq', '2022-01-09T18:30:00.000Z'), 
        ('created_date__gte', '2022-01-04T18:30:00.000Z'), 
        ('follow_up_status__eq', 'Open'), 
        ('role_name__eq', 'Pharmacist'), 
        ('last_response__eq', 'To-Patient')
)>

由于单个 OR 将按原样解除并且嵌套 AND 将显示为一个级别,因此它似乎奏效了。