代码之家  ›  专栏  ›  技术社区  ›  Boldewyn

如何过滤Django的commasepartedintegerfield

  •  5
  • Boldewyn  · 技术社区  · 14 年前

    假设一个模型

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

    的内容 bar 可能看起来,例如。, 12,35,67,142 .

    我想查询所有 Foo s、 有一个 42 在里面 酒吧 :

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

    结果不正确,因为 CommaSeparatedIntegerField 继承自 CharField 过滤器计算使用字段的字符串内容(将上面的示例与 142 也一样)。

    我怎么能有个过滤器呢 .split(",") 酒吧 在它检查 42个 ? 我真的不想 酒吧 成为 ManyToMany ,因为这将是一个可怕的开销。

    3 回复  |  直到 14 年前
        1
  •  13
  •   desfido    14 年前

    比如说:

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

    出于好奇,您是否检查过应用程序的实际性能,包括您描述的多对多方法和伪多对多方法?

        2
  •  0
  •   user4018217user4018217    10 年前

    这个答案是@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})
    
        3
  •  0
  •   cansadadeserfeliz    10 年前

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

    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)
    
    推荐文章