Django:如何过滤具有多对多关系的模型
Django: how to filter a model with ManyToMany relationships
我有一个通用的 ListView,我从中得到了一些通用的东西(这与我的问题无关)。
我的模型 Product
与 Tag
有多对多关系,即一个 Product
可以有多个 Tag
并且一个 Tag
可以链接到许多 Product
.
在这个通用的 ListView 中,我想过滤所有实际上有 Product
的 Tag
,这样客户可以点击 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)
returns全部Tag
,包括没有的Product
。如何过滤?
试试这个:
Tag.objects.filter(product_set__isnull=False).values_list('nom', flat=True)
找到了!首先,通过像这样使用 related_name
让 ManyToMany 关系更易读:
class Produit(BaseModel):
tags = models.ManyToManyField(Tag, related_name='produits')
然后这就是我如何获得 Produit
使用的所有 Tag
。我想它不是很优化,但它很有魅力:
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
我有一个通用的 ListView,我从中得到了一些通用的东西(这与我的问题无关)。
我的模型 Product
与 Tag
有多对多关系,即一个 Product
可以有多个 Tag
并且一个 Tag
可以链接到许多 Product
.
在这个通用的 ListView 中,我想过滤所有实际上有 Product
的 Tag
,这样客户可以点击 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)
returns全部Tag
,包括没有的Product
。如何过滤?
试试这个:
Tag.objects.filter(product_set__isnull=False).values_list('nom', flat=True)
找到了!首先,通过像这样使用 related_name
让 ManyToMany 关系更易读:
class Produit(BaseModel):
tags = models.ManyToManyField(Tag, related_name='produits')
然后这就是我如何获得 Produit
使用的所有 Tag
。我想它不是很优化,但它很有魅力:
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