Django查询不区分大小写的列表匹配

时间:2010-04-19 12:57:24

标签: django django-queryset

我有一个我希望匹配不区分大小写的名称列表,有没有办法在不使用下面的循环的情况下执行此操作?

a = ['name1', 'name2', 'name3']
result = any([Name.objects.filter(name__iexact=name) for name in a])

7 个答案:

答案 0 :(得分:34)

不幸的是,没有 __iin字段查找。但是有一个iregex可能有用,就像这样:

result = Name.objects.filter(name__iregex=r'(name1|name2|name3)')

甚至:

a = ['name1', 'name2', 'name3']
result = Name.objects.filter(name__iregex=r'(' + '|'.join(a) + ')')

请注意,如果a可以包含正则表达式中特殊的字符,则需要正确escape

新闻:在Djano 1.7中,可以创建自己的查找,因此您可以在正确初始化后实际使用filter(name__iin=['name1', 'name2', 'name3'])。有关详细信息,请参阅https://docs.djangoproject.com/en/1.7/ref/models/lookups/

答案 1 :(得分:19)

在Postgresql中,您可以尝试创建不区分大小写的索引,如下所述:

https://stackoverflow.com/a/4124225/110274

然后运行查询:

from django.db.models import Q
name_filter = Q()
for name in names:
    name_filter |= Q(name__iexact=name)
result = Name.objects.filter(name_filter)

索引搜索的运行速度将快于正则表达式匹配查询。

答案 2 :(得分:11)

使用django query functions和注释

的另一种方法
from django.db.models.functions import Lower
Record.objects.annotate(name_lower=Lower('name')).filter(name_lower__in=['two', 'one']

答案 3 :(得分:4)

请记住,至少在MySQL中,您必须在表中设置utf8_bin排序规则才能使它们区分大小写。否则它们保留大小写但不区分大小写。 E.g。

>>> models.Person.objects.filter(first__in=['John', 'Ringo'])
[<Person: John Lennon>, <Person: Ringo Starr>]
>>> models.Person.objects.filter(first__in=['joHn', 'RiNgO'])
[<Person: John Lennon>, <Person: Ringo Starr>]

因此,如果可移植性并不重要且您使用MySQL,则可以选择完全忽略该问题。

答案 4 :(得分:3)

添加Rasmuj所说的,逃避任何用户输入,如此

import re
result = Name.objects.filter(name__iregex=r'(' + '|'.join([re.escape(n) for n in a]) + ')')

答案 5 :(得分:1)

我正在将Exgeny的想法扩展为两个方面。

  function writeToDb (agent) {
    // Get parameter from Dialogflow with the string to add to the database
    const databaseEntry = agent.parameters.databaseEntry;

    // Get the database collection 'dialogflow' and document 'agent' and store
    // the document  {entry: "<value of database entry>"} in the 'agent' document
    const dialogflowAgentRef = db.collection('dialogflow').doc('agent');
    return db.runTransaction(t => {
      t.set(dialogflowAgentRef, {entry: databaseEntry});
      return Promise.resolve('Write complete');
    }).then(doc => {
      agent.add(`Wrote "${databaseEntry}" to the Firestore database.`);
    }).catch(err => {
      console.log(`Error writing to Firestore: ${err}`);
      agent.add(`Failed to write "${databaseEntry}" to the Firestore database.`);
    });
  }

答案 6 :(得分:0)

以下是自定义用户模型classmethod的示例,用于通过不区分大小写的电子邮件过滤用户

from django.db.models import Q

@classmethod
def get_users_by_email_query(cls, emails):
    q = Q()
    for email in [email.strip() for email in emails]:
        q = q | Q(email__iexact=email)
    return cls.objects.filter(q)