2015-11-18 48 views
3

Django的過濾器過濾所以,我有這種模式:與列表

class Product(models.Model): 
    colors = models.TextField(max_length=150,default = 'blue,green,blue') 

,我想用的顏色例如列表進行過濾。
任何想法,我該怎麼做呢?
colors = ["blue","green"]
我需要這樣的東西。

products = Product.objects.filter(colors__icontains = colors) 

我如何能修改模型來過濾任何形式的幫助或sugestion將apreciated。

+0

孩子是性別? – nthall

+0

哈哈。現在好多了 ? –

+0

另外,您可能希望使用'choices'屬性來選擇可能的顏色(如果您選擇不使用單獨的顏色模型) – Sayse

回答

1

既然你存儲的顏色爲純文本,而不是使用相關的模型沒有得到執行,你不能使用你想要的那種過濾器。

做正確的方法是使用ManyToManyField:顏色可以有多個產品,一個產品可以有多種顏色:

class Color(models.Model): 
    name = models.CharField(max_length=255) 

class Product(models.Model): 
    colors = models.ManyToManyField(Color, related_name='colors') 

然後,您可以添加顏色是這樣的:

blue = Color(name='blue') 
blue.save() 
red = Color(name='red') 
red.save() 
my_product = Product() 
my_product.save() 
my_product.colors.add(blue) 

如果你想查詢是紅色或藍色的所有產品,只是做:

Product.objects.filter(colors__in=[red, blue]) # Red and blue being Color instances 

如果您想獲得紅色和藍色的所有產品,只是做描述here

Product.objects.filter(colors=red).filter(colors=blue) # Red and blue being Color instances 

鏈接過濾器這樣不是特別方便,所以你可能需要一個定製QuerySet會爲你做它:

class AllManyToManyQuerySet(models.QuerySet): 
    def filter_all_many_to_many(self, attribute, *args): 
     qs = self 
     for arg in args: 
      qs = qs.filter(**{attribute: arg}) 
     return qs 

class Product(models.Model): 
    colors = models.ManyToManyField(Color, related_name='colors') 
    objects = AllManyToManyQuerySet.as_manager() 

而且使用它是這樣的:

Product.objects.all().filter_all_many_to_many('colors', red, blue) # red and blue being color instances 

另一個過濾器的方法是:

product_list = Product.objects.filter(reduce(operator.and_, [Q(colors__name=c) for c in colors])) 

這是未經測試,但它可能應該工作,你可以使用其他類的查詢集,如果你需要它在其他地方,讓你的代碼清潔和乾燥;)

+0

對不起,我忘了在QuerySet類中添加解壓縮! –

2

你可以只遍歷它,直到你需要的數據

products = Product.objects.all() 
for color in colors: 
    products = products.filter(colors__icontains=color) 
+0

任何想法,如果有可能使它在一條線上? :) –

+0

@RusMine - 它有可能使用'colors__in = colors'可能會起作用,但我沒有測試過(認爲它是錯誤的方式),否則,你用'icontains'嘗試了嗎? – Sayse

+0

@RusMine - 我不這麼認爲,但是對於它的價值,我認爲它很清楚這3條線在做什麼,可能有一種方法可以在一條線上構建一組過濾器,但這會讓人困惑得多這是什麼在這裏,這就是爲什麼我不想這樣顯示 – Sayse

1

對不起,我沒有得到這的邏輯操作:ANDOR您需要。但這並不重要。這裏是一個班輪:

from operator import or_, and_ # i'm not quite sure which one you actually need. 
from django.db.models import Q 

colors = ["blue","green"] 
Product.objects.filter(reduce(or_, [Q(colors__icontains=c) for c in colors])) 

但德興發言,我不能說有任何理由來存儲這些值這樣的。請考慮ArrayField,如果您因某種原因不想使用ManyToMany