Django manytomany字段过滤列表

时间:2016-08-08 00:52:14

标签: django

我正在打印一些与某些过滤器相匹配的啤酒列表,以及每个过滤器都有的栏。这些都处于多种关系中。我需要过滤这个条形列表,只显示给定状态的条形图。

我可以使用模板中的if语句来实现这一点,但是我无法将列表格式化为在最终项目之前使用带有'和'的逗号(如https://stackoverflow.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 个答案:

答案 0 :(得分:0)

您可以使用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关系使用预取也会提高性能,因为不会有尽可能多的数据库查找。