简体   繁体   English

Django QuerySet.union()-或QuerySet.raw()实现不区分大小写的Mutli-Search

[英]Django QuerySet.union() -or- QuerySet.raw() to Achieve Case-Insensitive Mutli-Search

Given a URL like this: 给定这样的URL:

http://..../search/?foo=a&foo=B&bar=whatever

In my View, I want to filter the QuerySet for CASE-INSENSITIVE matches of "foo". 在我的视图中,我想过滤查询集以查找“ foo”的不区分大小写的匹配项。 There's a handy "in" operator that I could use on my list of "foo", but it doesn't support case-insensitivity. 我可以在“ foo”列表中使用方便的“ in”运算符,但是它不支持不区分大小写。

To be clear, this (elegant code) performs a CASE-SENSITIVE match. 为了清楚起见,此(优雅代码)执行区分大小写的匹配。 (It doesn't match "foo=b".) I do not want this: (它与“ foo = b”不匹配。)我不想要这样:

    queryset = queryset.filter(foo__in=role)  # case-sensitive

My solution is to create a list of QuerySets, one for each "foo" match, and then to create return a final "union()" of the results. 我的解决方案是创建一个QuerySet列表,每个“ foo”匹配项一个,然后创建返回结果的最终“ union()”。

def get_queryset(self, **kwargs):
  queryset = super(PeopleListView, self).get_queryset()

  foo = self.request.GET.getlist('foo')
  if (len(foo) == 1):
    queryset = queryset.filter(foo__iexact=role[0])  # case-insensitive
  elif (len(foo) > 1):
    qs_list = []
    for _foo in foo:
      qs_list.append(queryset.filter(foo__iexact=_foo))
    queryset = Person.objects.none()  # EmptyQuerySet
    for qs in qs_list:
      queryset = queryset.union(qs)

  bar = self.request.GET.get('bar')
  if bar is not None:
    queryset = queryset.filter(bar__iexact=bar)  # Easy

This results in an error: 这会导致错误:

django.db.utils.DatabaseError: ORDER BY not allowed in subqueries of compound statements.

Is there a way to do this with "Q" objects? 有没有办法用“ Q”对象做到这一点?

If not, I think the "right" solution would involve converting the match patterns to lower-case, then using QuerySet::raw() to convert the database values to lower-case as well. 如果没有,我认为“正确”的解决方案将涉及将匹配模式转换为小写,然后使用QuerySet :: raw()将数据库值也转换为小写。 I'm a bit over my head there... 我在那儿有点头晕...

Thanks for your help! 谢谢你的帮助!

Well, here's the answer. 好吧,这就是答案。 Use "Q" objects! 使用“ Q”对象! :-) :-)

...
foo = self.request.GET.getlist('foo')
if (len(foo) > 0):
  q = Q()
  for _foo in foo:
    q |= Q(foo__iexact=_foo)
  queryset = queryset.filter(q)
...

Oh, and to support matching URLs like this: 哦,并支持这样的匹配URL:

http://..../fl/users/?foo=&bar=some_bar

which makes: 这使得:

<QueryDict: {'foo': [''], 'bar': ['some_bar']}>

I'll do this: 我将这样做:

...
foo = self.request.GET.getlist('foo')
if (len(foo) > 0):
  q = Q()
  for _foo in foo:
    if (_foo == ''):
      q |= Q(foo=None)
    else:
      q |= Q(foo__iexact=_foo)
  queryset = queryset.filter(q)
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM