如何在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)。希望这条评论能告诉那些来这里搜索“动态过滤器”之类的东西的人。