如何在Django中使用字段名、条件和值进行动态筛选

如何在Django中使用字段名、条件和值进行动态筛选,django,django-rest-framework,django-orm,django-filter,Django,Django Rest Framework,Django Orm,Django Filter,我有一个要求,即从客户端我将获得一个对象数组,该数组将具有字段名、过滤条件和类似的过滤值 对象的示例数组: [ {field_name: "book_name", filter_condition: "contains", filter_value: "some book name"}, {field_name: "book_category", filter_condition: "not_equal", filter_value: "category value"}, {field_n

我有一个要求,即从客户端我将获得一个对象数组,该数组将具有字段名、过滤条件和类似的过滤值

对象的示例数组:

[
 {field_name: "book_name", filter_condition: "contains", filter_value: "some book name"},
 {field_name: "book_category", filter_condition: "not_equal", filter_value: "category value"},
 {field_name: "book_author", filter_condition: "starts_with", filter_value: "authoer name"},
 {field_name: "book_price", filter_condition: "equal", filter_value: 100}
]
我必须根据以上所有条件进行过滤。考虑一下,我有一个带有名字簿的模型和对象数组中的字段(即BooKyNoname、BoojyCype、BooKuthAuthor、BoojyPalk)。对于filter_条件,我编写了一个函数来比较filter_条件并分配Django queryset API。比如说

def assign_filter_condition(self, request, filter_condition, field_name, filter_value):

   if filter_condition == "contains":
        kwargs = {
                '{0}__icontains'.format(field_name): filter_value
            }
        return kwargs
       ...

在这里,我不知道如何应用排除和非查询的条件

我真的不明白该怎么写这个逻辑。谁能帮我解释一下逻辑

def get_filter(self, field_name, filter_condition, filter_value):
        # thanks to the below post
        # https://stackoverflow.com/questions/310732/in-django-how-does-one-filter-a-queryset-with-dynamic-field-lookups
        # the idea to this below logic is very similar to that in the above mentioned post
        if filter_condition.strip() == "contains":
            kwargs = {
                '{0}__icontains'.format(field_name): filter_value
            }
            return Q(**kwargs)

        if filter_condition.strip() == "not_equal":
            kwargs = {
                '{0}__iexact'.format(field_name): filter_value
            }
            return ~Q(**kwargs)

        if filter_condition.strip() == "starts_with":
            kwargs = {
                '{0}__istartswith'.format(field_name): filter_value
            }
            return Q(**kwargs)
        if filter_condition.strip() == "equal":
            kwargs = {
                '{0}__iexact'.format(field_name): filter_value
            }
            return Q(**kwargs)

        if filter_condition.strip() == "not_equal":
            kwargs = {
                '{0}__iexact'.format(field_name): filter_value
            }
            return ~Q(**kwargs)

def get(self, request):
    # getting the array of objects data to filter. The array of objects data 
    # example is in the question
    filter_data = request.query_params.getlist('filterData[]')

    all_books = Books.objects.all()
    # Creating initial Q object
    filter_objects = Q()

    # Looping through the array of objects
    for data in filter_data:
        # The main part. Calling get_filter and passing the filter object data.
        filter_objects &= self.get_filter(
                data["fieldName"], data["filterCondition"],
                data["filterValue"])
    filtered_data = all_books.filter(filter_objects)


提前谢谢。

您可以使用dict解包 请注意,您不需要条件,所以作为一个dict,数组是足够的 下面的代码将引导您到您想要的地方

条件=[
(“书名”、“包含”、“某些书名”),
(“账面类别”、“不相等”、“类别价值”),
(“书的作者”、“以”、“作者姓名”开头”),
(“账面价格”,“同等”,100)
]
def get_过滤器(值):
名称、条件、值=值
key=f“{name}{condition}”
返回键、值
过滤器=dict(映射(获取过滤器,条件))
qs=qs.filter(**filters)

在浏览了几篇StackOverflow文章之后,我找到了逻辑。下面是逻辑

def get_filter(self, field_name, filter_condition, filter_value):
        # thanks to the below post
        # https://stackoverflow.com/questions/310732/in-django-how-does-one-filter-a-queryset-with-dynamic-field-lookups
        # the idea to this below logic is very similar to that in the above mentioned post
        if filter_condition.strip() == "contains":
            kwargs = {
                '{0}__icontains'.format(field_name): filter_value
            }
            return Q(**kwargs)

        if filter_condition.strip() == "not_equal":
            kwargs = {
                '{0}__iexact'.format(field_name): filter_value
            }
            return ~Q(**kwargs)

        if filter_condition.strip() == "starts_with":
            kwargs = {
                '{0}__istartswith'.format(field_name): filter_value
            }
            return Q(**kwargs)
        if filter_condition.strip() == "equal":
            kwargs = {
                '{0}__iexact'.format(field_name): filter_value
            }
            return Q(**kwargs)

        if filter_condition.strip() == "not_equal":
            kwargs = {
                '{0}__iexact'.format(field_name): filter_value
            }
            return ~Q(**kwargs)

def get(self, request):
    # getting the array of objects data to filter. The array of objects data 
    # example is in the question
    filter_data = request.query_params.getlist('filterData[]')

    all_books = Books.objects.all()
    # Creating initial Q object
    filter_objects = Q()

    # Looping through the array of objects
    for data in filter_data:
        # The main part. Calling get_filter and passing the filter object data.
        filter_objects &= self.get_filter(
                data["fieldName"], data["filterCondition"],
                data["filterValue"])
    filtered_data = all_books.filter(filter_objects)


希望它能帮助别人。:)

创建一个从DjangoFilterBackends继承的类,并使用而不是此

class MyFilterBackend(DjangoFilterBackend):
    def get_filterset_kwargs(self, request, queryset, view):
        data = request.query_params
        data._mutable = True
        for item in data:
            try:
                print(item)
                field = getattr(queryset.model, item)
                field: DeferredAttribute
                data[item] = [x for x in list(field.field.choices) if x[1] == data[item]][0][0]
            except:
                pass
        return {
            'data': request.query_params,
            'queryset': queryset,
            'request': request,
        }

我不知道您的使用情况或工作条件,但您至少应该有理由拒绝使用Django filter@nigel222我在问题中提到的上述对象示例数组,就像我将向DRF发送请求一样。因为您可以看到筛选条件和字段名将发生更改。所以我不知道如何处理它或在后端编写逻辑。好吧,Django filter可能不是适合您使用的工具(DRF)。希望这条评论能告诉那些来这里搜索“动态过滤器”之类的东西的人。