2010-03-02 78 views
4

在Django中几乎所有的查找都有一个不区分大小写的版本,除了它,看起来像。有没有办法在Django中进行不区分大小写的IN查询?

这是一个问题,因为有时我需要做一个查找,我肯定案件会不正确。

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

我能做些什么来解决这个问题吗?有人提出一个黑客来解决这个问题?

+1

我觉得很奇怪。至少在MySql上,似乎__in查找是不区分大小写的。 – 2012-08-11 06:06:44

回答

6

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

以下是一种这样做,无可否认,它是笨重的。

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) 
+0

+1尽管它不优雅:) – 2010-10-12 17:40:37

1

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

+0

不幸的是,被查找的对象可能是小写字母或混合大小写,并且不可能限制它。 – 2010-03-03 21:07:58

0

痘痘更优雅的方式将是这样:

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

我不明白这是多么优雅。 Products.objects.all()可能会返回*数千行,然后将其过滤到数据库之外,然后将其作为列表返回,而不是作为查询,这意味着您无法对其进行排序(很容易)或在其上执行额外的过滤器。刚刚意识到你每次都循环访问'user_entered_data_as_list' *所以每个人都这样做,除非你的表非常小,否则不要使用这种技术。 – 2012-09-24 15:14:32

+0

刚做了一个测试,你的方法需要用30k +记录的表格长200倍左右:http://pastebin.com/R78P0Pdq – 2012-09-24 17:43:20

+0

虽然你可以尝试使用生成器而不是简单列表,但它并不有效。 – sepulchered 2012-10-12 10:45:26

1

这里是不需要的情况下,准备DB值的解决方案。 此外,它在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]) 
1

另一个解决方案 - 尽管原油 - 是包含原始字符串的不同情况列表“in”过滤器的参数。例如:不是['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 
1

如果你的数据库是MySQL的,Django的治疗在不区分大小写查询情况。虽然我不知道别人

编辑1:

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

会给下面的结果在哪个城市的名字是

东京 TOKIO tokio or Paris 巴黎,巴黎

+0

你能多解释一下吗? – 2016-05-20 11:21:16

+0

我的意思是,如果您在Django ORM系统中使用MYSQL数据库,那么所有IN查询都不区分大小写。 – 2016-05-20 14:03:51

+0

去@DieterMeemken我用一个例子编辑了我的答案。 – 2016-05-20 14:11:57

相关问题