2010-11-15 101 views
4

假設一個模型如何篩選Django的CommaSeparatedIntegerField

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

bar的內容可能看起來像,例如,12,35,67,142

我想查詢所有Foo的時候,那些有42bar

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

不給出正確的結果,因爲從CharFieldCommaSeparatedIntegerField繼承和過濾器評價使用的字符串內容字段(以上示例也與142匹配)。

我如何擁有一個篩選器,在bar字段上執行.split(","),然後檢查42?我真的不希望bar成爲ManyToMany,因爲這將是一個可怕的開銷。

回答

12

什麼是這樣的:

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

出於好奇的線獨立的功能,你檢查你的應用程序W的實際性能/都很多一對多的方式,和僞多對一你描述的多對多的方法?

+1

謝謝!是的,它是冗長的,但它完成了這項工作。一句話:人們必須測試一個確切的'42,',也是(尾隨的逗號),因爲這個字段也是有效的。 – Boldewyn 2010-11-15 13:00:04

0

這個答案是@desfido答案的一個擴展。基本上將過濾CommaSeperatedInteger字段的函數與對象類型分離。發現這個解決方案比使用正則表達式找到正確值更快。我使用了這個正則表達式。

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