有没有办法在Django中进行不区分大小写的IN查询?

时间:2010-03-02 03:54:49

标签: django django-queryset case-sensitive

Django中几乎所有类型的查找都有一个不区分大小写的版本,除了它,它就会出现。

这是一个问题,因为有时我需要进行查找,我确定案例不正确。

Products.objects.filter(code__in=[user_entered_data_as_list])

我有什么办法可以解决这个问题吗?让人们想出来解决这个问题吗?

7 个答案:

答案 0 :(得分:7)

我通过使MySQL数据库本身不区分大小写来解决这个问题。我怀疑Django的人是否有兴趣将其添加为功能或提供有关如何提供自己的字段查找的文档(假设甚至可以在不为每个数据库后端提供代码的情况下)

这是一种方法,诚然这是笨重的。

products = Product.objects.filter(**normal_filters_here)
results = Product.objects.none()
for d in user_entered_data_as_list:
    results |= products.filter(code__iexact=d)

答案 1 :(得分:1)

如果它不会产生冲突,可能的解决方法可能是在保存对象和filter时将字符串转换为大写或小写。

答案 2 :(得分:1)

这是一个不需要案例准备的DB值的解决方案。 此外,它在数据库引擎方面进行过滤,这意味着比在objects.all()上迭代更多的性能。

def case_insensitive_in_filter(fieldname, iterable):
    """returns Q(fieldname__in=iterable) but case insensitive"""
    q_list = map(lambda n: Q(**{fieldname+'__iexact': n}), iterable)
    return reduce(lambda a, b: a | b, q_list)

另一种有效的解决方案是使用额外的可移植的原始SQL lower()函数:

MyModel.objects.extra(
    select={'lower_' + fieldname: 'lower(' + fieldname + ')'}
).filter('lover_' + fieldname + '__in'=[x.lower() for x in iterable])

答案 3 :(得分:1)

另一个解决方案 - 尽管很粗糙 - 是在“in”过滤器的list参数中包含原始字符串的不同情况。例如:代替['a','b','c'],改为使用['a','b','c','A','B','C']。

这是一个从字符串列表构建这样一个列表的函数:

def build_list_for_case_insensitive_query(the_strings):
    results = list()
    for the_string in the_strings:
        results.append(the_string)
        if the_string.upper() not in results:
            results.append(the_string.upper())
        if the_string.lower() not in results:
            results.append(the_string.lower())
    return results

答案 4 :(得分:1)

如果您的数据库是MySQL,Django会对IN查询区分大小写。虽然我不确定其他人

修改1:

model_name.objects.filter(location__city__name__in': ['Tokio','Paris',])

将提供以下结果,其中城市名称为

  

Tokio TOKIO tokio或Paris < / strong>巴黎或巴黎

答案 5 :(得分:0)

更优雅的方式是:

[x for x in Products.objects.all() if x.code.upper() in [y.upper() for y in user_entered_data_as_list]]

答案 6 :(得分:0)

可以构建使用Q object的查找来仅一次访问数据库:

from django.db.models import Q

user_inputed_codes = ['eN', 'De', 'FR']

lookup = Q()
for code in user_inputed_codes:
    lookup |= Q(code__iexact=code)
filtered_products = Products.objects.filter(lookup)