2014-09-13 99 views
1

簡單的模型在標籤字段上具有多對多關係。Django過濾器推演ManyToMany

class Tag(models.Model): 
    description = models.TextField() 

class Species(models.Model): 
    name = models.CharField(max_length=256) 
    tags = models.ManyToManyField(Tag) 

現在我試着這一點,據我瞭解,它應該返回一個,每一個tag_description在標籤列表匹配列表:

tag_list = request.GET.get('q').split(',') 
species = Species.objects.filter(reduce(and_, [Q(tags__description=c) for c in tag_list])) 

但它返回一個空列表。它應該返回一些對象。

它工作時,我給它只是一個標籤

任何想法,爲什麼發生這種情況?

進出口使用它作爲這個答案顯示: https://stackoverflow.com/a/8636836/228660

回答

1

正如你在這個問題的意見實際上看到,它實際上並沒有工作;) 的問題是,您將使用所有過濾器都使用相同的連接(即相同的對象)。除非tag_list中的所有項目都是相同的,否則這將無法使用。問題在於Q對象而不是完全過濾的查詢。

tag_list = request.GET.get('q').split(',') 

# Generate a query with all species 
all_species = Species.objects.all() 
# Generate a list with the separately filtered species 
filtered_species = [all_species.filter(tags__description=c) for c in tag_list] 
# Join the filtered species together using the same method :) 
species = reduce(and_, filtered_species, all_species) 
+0

啊哈,謝謝!但是這會給我一個基於OR的列表。在那裏,因爲我只想要與列表中的所有項目匹配的產品 – Harry 2014-09-13 09:57:16

+1

糟糕...您是對的,在這種情況下,並不像我希望的那麼容易:)我會更新答案。 – Wolph 2014-09-13 10:00:54

+0

很好,這個工程。它會如何比較:\t species = Species.objects.filter(tags__description__in = tag_list).annotate(num_tags = Count('tags__description')).filter(num_tags = len(tag_list)) – Harry 2014-09-13 10:12:55

1

我想這樣做的另一個方法是:

tag_list = request.GET.get('q').split(',') 
species = Species.objects.all().distinct() 
for tag in tag_list: 
    species = species.filter(tags__description=tag) 
else: 
    species = Species.objects.none()