如何过滤Django';s CommaseparatedTegerfield
假设一个模型如何过滤Django';s CommaseparatedTegerfield,django,django-models,filter,field,Django,Django Models,Filter,Field,假设一个模型 class Foo(models.Model): bar = models.CommaSeparatedIntegerField('Filter Me!') 条的内容可能看起来像,例如12,35,67142 我想查询所有Foos,它们在bar中有42: all_42_foos = Foo.objects.filter(bar__contains="42") 这不会给出正确的结果,因为CommaSeparatedIntegerField继承自CharField,并且过滤器
class Foo(models.Model):
bar = models.CommaSeparatedIntegerField('Filter Me!')
条
的内容可能看起来像,例如12,35,67142
我想查询所有Foo
s,它们在bar
中有42
:
all_42_foos = Foo.objects.filter(bar__contains="42")
这不会给出正确的结果,因为CommaSeparatedIntegerField
继承自CharField
,并且过滤器计算使用字段的字符串内容(也将上述示例与142
匹配)
在检查
42
之前,如何使用在栏上执行.split(“,”
的过滤器?我真的不想把bar
变成一个manytomy
,因为这将是一个可怕的开销。像这样的东西怎么样:
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) )
出于好奇,您是否检查了应用程序的实际性能,包括多对多方式,您正在描述的伪多对多方法?此答案是@desfido答案的扩展。基本上,将对象类型与过滤CommaseOperatedInteger字段的函数解耦。结果表明,此解决方案比使用正则表达式查找正确值更快。我使用了此正则表达式
_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})
也可以将其写入一个正则表达式:
all_42_foos = Foo.objects.filter(bar__regex=u'^42,|,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)