【问题标题】:Two foreign keys and a value in django templatedjango模板中的两个外键和一个值
【发布时间】:2011-04-14 15:03:21
【问题描述】:

我是 django 的新手,所以这个问题可能很愚蠢,但如果你知道,请随时教我正确的方法。 我试着用谷歌搜索这个问题,但我仍然不知所措。 这是我的问题:

我的模型中有一个类,它有两个外键:

class X(models.Model):
    name = models.CharField(max_length=30)
    def __unicode__(self):
        return name

class Y(models.Model):
    name = models.CharField(max_length=30)
    def __unicode__(self):
        return name

class Z(models.Model):
    name = models.CharField(max_length=30)
    x = models.ForeignKey(X)
    y = models.ForeignKey(Y)
    def __unicode__(self):
        return name

在我看来,我得到了 X 对象的部分列表和 Y 对象的部分列表,如下所示:

def MyView(x_pattern, y_pattern):
    x_list = X.objects.filter(name__contains=x_pattern)
    y_list = Y.objects.filter(name__contains=y_pattern)
    z_list = Z.objects.all()
    return render_to_response({'x_list': x_list, 'y_list': y_list, 'z_list': z_list})

在我的模板中,我希望能够像这样显示一个表格:

<table>
  <tr>
   <td>Y</td>
   {% for x in x_list %}
    <td>{{ x }}</td>
   {% endfor %}
  </tr>
  {% for y in y_list %}
   <tr>
    <td>{{ y }}</td>
    {% for x in x_list %}
     <td>
      <!-- here I need help: 
           I need to display z[x, y] if it exists, or "N/A" otherwise.
      -->
     </td>
    {% endfor %}
   </tr>
  {% endfor %}

如何在 django 中正确执行此操作?

非常感谢,

【问题讨论】:

    标签: django django-models django-templates django-views


    【解决方案1】:

    作为@DZPM suggested,您应该考虑将逻辑保留在您的视图中。 [愚蠢] 我曾经发明了自己的“表”数据结构来做一些非常相似的事情。该表的行对应于X,列对应于Y,单元格对应于Z[X, Y]。然后我写了get_rowget_cell 过滤器来完成模板中的技巧。 [/sheepish]

    也就是说,您可以使用一对自定义过滤器来实现您想要的。这个解决方案比较冗长。

    @register.filter
    def x_is(value, x):
        return value.x == x
    
    @register.filter
    def y_is(value, y):
        return value.y == y
    

    您可以在模板中使用这些过滤器,如下所示:

    {% if z|x_is:x and z|y_is:y %}
        {{ z }}
    {% else %}
        N/A
    {% endif %}
    

    【讨论】:

    • 宾果游戏!非常感谢 - 那是缺少的链接(自定义过滤器)。
    【解决方案2】:

    您应该将逻辑保留在您的视图中。为什么不直接过滤 z_list 呢?

    z_list = Z.objects.filter(x__name__contains=x_pattern, y__name__contains=y_pattern)
    

    【讨论】:

    • 我可以过滤视图中的列表,但它仍然不能帮助我正确显示它(即我需要将 (x,y) 密钥对映射到 z[x,y] 中的值模板,以便在适当的表格单元格中显示它)。我在这里错过了什么吗?
    【解决方案3】:

    另一种方法是在您的视图中创建一个生成器,然后将其发送到您的模板上下文:

    # nested inside your view function
    def x_and_z_list(y):
        for x in x_list:
            z_obj = x.z_set.filter(y=y)
            z_name = z_obj or 'N/A'
            yield {'x': x, 'z': z_name}
    return render_to_response('mytemplate', {'list_generator': x_and_z_list}
    

    那么您的模板可能如下所示:

    {% for y in y_list %}
        <tr>
            <td>{{ y }}</td>
            {% for pair in list_generator.y %}  {# pair is the dict you yielded before #}
                <td>{{ pair.x.name }}: {{ pair.z }}</td>
            {% endfor %}
        </tr>
    {% endfor %}
    

    【讨论】:

      【解决方案4】:

      我将自定义过滤器和函数的概念作为第一类对象组合在一起,将模板过滤器制成函子(函数对象)。

      这是我最终做的:

      def z_filter(x, y):
          z_list = list(Z.objects.filter(x, y))
          return z_list.pop().name or 'N/A'
      register.filter(z_filter)
      

      在模板中:

      {% load z_filter %}
      <table>
       <tr>
        <td>Y</td>
        {% for x in x_list %}
         <td>{{ x }}</td>
        {% endfor %}
       </tr>
       {% for y in y_list %}
        <tr>
         <td>{{ y }}</td>
          {% for x in x_list %}
           <td>{{ x|z_filter:y }}</td>
          {% endfor %}
         </tr>
       {% endfor %}
      </table>
      

      感谢大家的帮助!

      【讨论】:

        猜你喜欢
        • 2019-07-30
        • 2015-12-21
        • 2011-12-04
        • 1970-01-01
        • 1970-01-01
        • 2021-07-12
        • 2017-06-27
        • 2010-10-07
        相关资源
        最近更新 更多