Django管理员搜索:如何允许OR运算符之间搜索条件? [英] Django admin search: how to allow OR operator between search terms?

查看:134
本文介绍了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆