如何过滤Django的CommaSeparatedIntegerField

时间:2010-11-15 11:55:09

标签: django django-models filter field

假设一个模型

class Foo(models.Model):
    bar = models.CommaSeparatedIntegerField('Filter Me!')

bar的内容可能如下,例如12,35,67,142

我想查询Foo中有42的所有bar

all_42_foos = Foo.objects.filter(bar__contains="42")

没有给出正确的结果,因为CommaSeparatedIntegerField继承自CharField,过滤器评估使用字段的字符串内容(上面的例子也与142匹配)

在检查.split(",")之前,如何在bar字段上执行42过滤器?我真的不希望bar成为ManyToMany,因为它是一个可怕的开销。

3 个答案:

答案 0 :(得分:13)

如下:

from django.db.models import Q

all_42_foos = Foo.objects.filter( Q(bar__startswith='42,') | Q(bar__endswith=',42') | Q(bar__contains=',42,') | Q(bar__exact='42') )

虽然这是一个冗长的查询,但我认为沿着这些方向的某些东西将是获得你所寻找的东西的唯一途径。可能值得把它变成一个单独的函数

def all_x_foos(x):
    return Foo.objects.filter( Q(bar__startswith=x+',') | Q(bar__endswith=','+x) | Q(bar__contains=',{0},'.format(x)) | Q(bar__exact=x) )

出于好奇,您是否已经使用多对多方式和您描述的伪多对多方法检查了应用的实际性能?

答案 1 :(得分:0)

这个答案是@desfido的答案的扩展。基本上将对象类型与过滤CommaSeperatedInteger字段的函数解耦。转出此解决方案比使用正则表达式找到正确的值更快。我使用了这个正则表达式。< / p>

_regex = r"(^|(\d*,)+)(%s)((,\d*)+|$)" %('|'.join(_ids))

如果要在逗号分隔值中搜索多个值,可以在循环中调用下面给出的函数

此功能的关键字参数为: -

cs_field_name将是逗号分隔整数字段的名称。

x将是要搜索的整数。

它返回一个Q对象,然后可以将其组合并用于过滤

def search_comma_seperated_field(cs_field_name,x):
    startswith_key = cs_field_name + "__startswith"
    endswith_key = cs_field_name + "__endswith"
    contains_key = cs_field_name + "__contains"
    exact_key = cs_field_name + "__exact"
    return Q(**{startswith_key : x+','}) | \
                                     Q(**{endswith_key:','+x}) |\
                                     Q(**{contains_key : ',{0},'.format(x)}) |\
                                     Q(**{exact_key:x})

答案 2 :(得分:0)

您也可以用一个正则表达式编写它:

all_42_foos = Foo.objects.filter(bar__regex=u'^42,|,42,|,42$|^42$')

bar_number = 42
bar_regex = r'^{0},|,{0},|,{0}$|^{0}$'.format(bar_number)
all_42_foos = Foo.objects.filter(bar__regex=bar_regex)