2015-07-30 5 views
0

У меня есть общий ListView, где я получаю некоторые общие вещи (это не связано с моим вопросом).Django: как фильтровать модель с отношениями ManyToMany

У меня модель Product, которая имеет отношение ManyToMany с Tag т.е. Product может иметь много TagTag и может быть связан со многими Product.

В этом общем списке ListView я хочу отфильтровать все Tag, у которых есть фактически Product, чтобы клиент мог нажать на Tag, и я мог бы фильтровать позже.

До сих пор я пришел к этому:

class IndexView(generic.ListView): 
    template_name = 'produits/index.html' 
    context_object_name = 'liste_produits' 

    def get_queryset(self): 
     """Return the last five created products.""" 
     return Produit.objects.order_by('-date_v_fin', '-date_v_debut')[:5] 

    def get_context_data(self, **kwargs): 
     context = super(IndexView, self).get_context_data(**kwargs) 
     context['produits_tags'] = list(
      Tag.objects.values_list('nom', flat=True) 
     ) 
     context['produits_tags'].insert(0, _("Tous")) 
     return context 

Но Tag.objects.values_list('nom', flat=True) возвращает все Tag, в том числе тех, у кого нет Product. Как отфильтровать это?

+1

Я не совсем понимаю, что вам нужно. Вы просто хотите показать все теги, у которых есть продукт, или вы хотите перебирать продукты и показывать теги для каждого из них? –

+0

@ DanielRoseman Я хочу показать все теги, которые имеют продукт –

ответ

0

Нашел! Прежде всего, сделать отношения ManyToMany более читаемым наоборот, используя related_name так:

class Produit(BaseModel): 
    tags = models.ManyToManyField(Tag, related_name='produits') 

Тогда вот как я получаю все Tag, которые используются при Produit. Я думаю, это не очень оптимизировано, но оно работает как шарм:

class IndexView(generic.ListView): 
    #blabbla ignoring code in-between 
    def get_context_data(self, **kwargs): 
     context = super(IndexView, self).get_context_data(**kwargs) 
     context['produits_tags'] = list(
      Tag.objects.filter(produits__in=Produit.objects.all()).distinct() 
     ) 
     context['produits_tags'].insert(0, _("All")) 
     return context 
0

попробовать это:

Tag.objects.filter(product_set__isnull=False).values_list('nom', flat=True) 
+0

Это не работает. –

+0

Я пробовал обратный путь: 'Produit.tags.values_list ('nom', flat = True)' и я получаю эту ошибку: 'Объект ReverseManyRelatedObjectsDescriptor 'не имеет атрибута' values_list'' –

Смежные вопросы