Django 多对多字段过滤器列表

Posted

技术标签:

【中文标题】Django 多对多字段过滤器列表【英文标题】:Django manytomany field filter list 【发布时间】:2016-12-13 16:21:16 【问题描述】:

我正在打印与某些过滤器匹配的啤酒列表,以及每个都可以点击的酒吧。这些是多对多关系。我需要过滤此条形列表以仅显示处于给定状态的条形。

我可以使用模板中的 if 语句来实现这一点,但是我无法将列表格式化为在最后一项之前使用带有“和”的逗号(如 https://***.com/a/3649002/6180992),因为我不知道列表。

我已经想到了三种可能的方法,但无法使任何一种工作:

过滤与酒吧相关的字段以及视图中的啤酒 在模板中组装列表,然后再次循环打印它 过滤模板中的条形相关字段

以下是相关的代码部分:

models.py

class Bar(models.Model):
    bar = models.CharField(max_length=200, default='FinshnPig')
    state = models.CharField(max_length=200,default='NY')

    def __str__(self):
        return self.bar
    class Meta:
        ordering = ('bar','region')


class Tap(models.Model):
    bar = models.ManyToManyField(Bar,default='FinshnPig')
    brewery = models.CharField(max_length=200)
    beer = models.CharField(max_length=200)
    state = models.CharField(max_length=200, default='NY')

    def __str__(self):
        return self.beer            

views.py

f = TapFilter(request.GET, queryset=Tap.objects.filter(state="VIC"))

模板:

% for tap in filter %
  <li>
  <b> tap.beer </b>
  <em> tap.brewery </em>
  @% for bar in tap.bar.all %% if bar.state == "VIC" % bar.bar </b>% endif %% include "taplists/comma.html" %% endfor %
  </li>
% endfor %

【问题讨论】:

【参考方案1】:

您可以使用prefetch 只查询相关栏,然后再将其发送到模板,如下所示:

prefetch =  Prefetch(
    'bar', 
    queryset=Bar.objects.filter(state=CHOSEN_STATE),
    to_attr='selected_states'
)
filter = Tap.objects.filter(state=CHOSEN_STATE).prefetch_related(prefetch)

现在在您的模板中使用您分配的自定义属性:

% for tap in filter %
   # Now selected_bars only contains the bars in the state you want
   % for bar in tap.selected_bars.all %
   ...
   % endfor %
% endfor %

prefetch_related 的 Django 文档的其他信息

注意:对ManyToMany 关系使用预取也会提高性能,因为不会有那么多数据库查找。

【讨论】:

谢谢!我只需要删除模板中的 .all,否则效果非常好!

以上是关于Django 多对多字段过滤器列表的主要内容,如果未能解决你的问题,请参考以下文章

如何以 django 形式过滤多对多字段

在Django中按关系字段过滤多对多关系

过滤多对多字段Django

Django 查询集过滤具有相同多对多字段的对象

如何过滤和访问 Django QuerySet 中的多对多字段?

Django Rest Framework(多对多字段上的 GET 过滤器)