Django管理员搜索:如何允许OR运算符之间搜索条件? [英] Django admin search: how to allow OR operator between search terms?
本文介绍了Django管理员搜索:如何允许OR运算符之间搜索条件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
添加这些功能最简单的方法是什么?
谢谢
解决方案
这是一个更完整的代码段:
<$从django.contrib.admin.views.main导入ChangeList
从django.db导入模型
import操作符
class MyChangeList(ChangeList )
def __init __(self,* a):
super(MyChangeList,self).__ init __(* a)
def get_query_set(self,request):
#我们收集所有声明的列表过滤器。
(self.filter_specs,self.has_filters,remaining_lookup_params,
use_distinct)= self.get_filters(request)
#然后,我们让每个列表过滤器将查询器修改为其喜好。
qs = self.root_query_set
for self.filter_specs中的filter_spec
new_qs = filter_spec.queryset(request,qs)
如果new_qs不为None:
qs = new_qs
try:
#最后,我们从查询
#string中应用剩余的查询参数(即那些尚未被
#过滤器)。
qs = qs.filter(** remaining_lookup_params)
除了(可疑操作,不正确配置):
#允许某些类型的错误按原样重新提升,以便
#来电可以以特殊的方式对待他们。
raise
除了异常,e:
#每个其他错误都被一个裸体捕获,除了,因为我们没有
#有任何其他验证查找参数的方法。如果关键字参数不正确,或者
#的值不正确,则可能是
#无效,所以我们可能会得到FieldError,
#ValueError,ValidationError或?
raise incorrectLookupParameters(e)
#使用select_related(),如果其中一个list_display选项是具有关系的字段
#,并且所提供的查询器还没有
#select_related defined。
如果不是qs.query.select_related:
如果self.list_select_related:
qs = qs.select_related()
else:
for self_namelist_display中的field_name:
try:
field = self.lookup_opts.get_field(field_name)
except models.FieldDoesNotExist:
pass
else:
if isinstance(field.rel, models.ManyToOneRel):
qs = qs.select_related()
break
#设置排序。
ordering = self.get_ordering(request,qs)
qs = qs.order_by(* ordering)
#应用关键字搜索。
def construct_search(field_name):
如果field_name.startswith('^'):
返回%s__istartswith%field_name [1:]
elif field_name.startswith('= '):
返回%s__iexact%field_name [1:]
elif field_name.startswith('@'):
返回%s__search%field_name [1:]
else:
返回%s__icontains%field_name
如果self.search_fields和self.query:
orm_lookups = [construct_search(str(search_field))
self.search_fields中的search_field]
or_queries = []
for self.query.split()中的位:
or_queries + = [models.Q(** {orm_lookup:bit})$ orm_lookups中的orm_lookup的b $ b]
如果len(or_queries)> 0:
qs = qs.filter(reduce(operator.or_,or_queries))
如果不是use_distinct:
在orm_lookups中的search_spec:
如果lookup_needs_distinct(self.lookup_opts,search_spec )
use_distinct = True
break
如果use_distinct:
返回qs.distinct()
其他:
返回qs
和您的ModelAdmin
def get_changelist(* a,** k):
return MyChangeList
django-sphinx seems to be a bit of an overkill.
What's the simplest way to add such functionality?
Thanks
解决方案
Here's a more complete snippet:
from django.contrib.admin.views.main import ChangeList
from django.db import models
import operator
class MyChangeList(ChangeList):
def __init__(self, *a):
super(MyChangeList, self).__init__(*a)
def get_query_set(self, request):
# First, we collect all the declared list filters.
(self.filter_specs, self.has_filters, remaining_lookup_params,
use_distinct) = self.get_filters(request)
# Then, we let every list filter modify the queryset to its liking.
qs = self.root_query_set
for filter_spec in self.filter_specs:
new_qs = filter_spec.queryset(request, qs)
if new_qs is not None:
qs = new_qs
try:
# Finally, we apply the remaining lookup parameters from the query
# string (i.e. those that haven't already been processed by the
# filters).
qs = qs.filter(**remaining_lookup_params)
except (SuspiciousOperation, ImproperlyConfigured):
# Allow certain types of errors to be re-raised as-is so that the
# caller can treat them in a special way.
raise
except Exception, e:
# Every other error is caught with a naked except, because we don't
# have any other way of validating lookup parameters. They might be
# invalid if the keyword arguments are incorrect, or if the values
# are not in the correct type, so we might get FieldError,
# ValueError, ValidationError, or ?.
raise IncorrectLookupParameters(e)
# Use select_related() if one of the list_display options is a field
# with a relationship and the provided queryset doesn't already have
# select_related defined.
if not qs.query.select_related:
if self.list_select_related:
qs = qs.select_related()
else:
for field_name in self.list_display:
try:
field = self.lookup_opts.get_field(field_name)
except models.FieldDoesNotExist:
pass
else:
if isinstance(field.rel, models.ManyToOneRel):
qs = qs.select_related()
break
# Set ordering.
ordering = self.get_ordering(request, qs)
qs = qs.order_by(*ordering)
# Apply keyword searches.
def construct_search(field_name):
if field_name.startswith('^'):
return "%s__istartswith" % field_name[1:]
elif field_name.startswith('='):
return "%s__iexact" % field_name[1:]
elif field_name.startswith('@'):
return "%s__search" % field_name[1:]
else:
return "%s__icontains" % field_name
if self.search_fields and self.query:
orm_lookups = [construct_search(str(search_field))
for search_field in self.search_fields]
or_queries = []
for bit in self.query.split():
or_queries += [models.Q(**{orm_lookup: bit})
for orm_lookup in orm_lookups]
if len(or_queries) > 0:
qs = qs.filter(reduce(operator.or_, or_queries))
if not use_distinct:
for search_spec in orm_lookups:
if lookup_needs_distinct(self.lookup_opts, search_spec):
use_distinct = True
break
if use_distinct:
return qs.distinct()
else:
return qs
and in your ModelAdmin
def get_changelist(*a, **k):
return MyChangeList
这篇关于Django管理员搜索:如何允许OR运算符之间搜索条件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文