【问题标题】:How to render Django query set as column wise into html table?如何将 Django 查询集按列呈现到 html 表中?
【发布时间】:2018-05-09 14:30:39
【问题描述】:

假设我的 sql 表看起来像这样..

产品表

--------------------------------
| id | Model| Manufacturer     |
--------------------------------
| 1  | ABC  | Samsung          |
| 2  | XYZ  | LG               | 
| 3  | ZYX  | Sony             |
--------------------------------

在 django 视图中,我从该表中获取所有记录并将其传递给模板..

def compare(request):
    product_ids = request.GET.get('product_ids')
    products = Product.objects.filter(id__in=product_ids)
    return render(request, 'compare.html', {'products': products})

由于 query_set 结果记录一个接一个地出现,我们可以说它是按行排列的,但是对于模板中的这种情况,我想创建一个 html 表,结果应该是这样的..

--------------------------------------------
|id           | 1       | 2        | 3     |
|Model        | ABC     | XYZ      | ZYX   |
|Manufacturer | Samsung | LG       | Sony  |
--------------------------------------------

通过查看上面的示例,您可以看到数据按列呈现。

所以请在 Django 中建议我一个更好的方法,我可以通过它来实现这一点,如果我错了,请纠正我,因为我是 Django 的初学者。

提前致谢

【问题讨论】:

    标签: python django html-table django-templates django-views


    【解决方案1】:

    使用 values_list() 并将您的查询集转换为列表

    products = list(Product.objects.filter(id__in=product_ids).values_list('id', 'Model', 'Manufacturer'))
    # OUTPUT: [(1, 'ABC', 'Samsung'), (2, 'XYZ', 'LG'), (3, 'ZYX', 'Sony')]
    

    现在使用 zip

    转置这个二维矩阵
    t_products = list(zip(*products))
    # OUTPUT: [(1, 2, 3), ('ABC', 'XYZ', 'ZYX'), ('Samsung', 'LG', 'Sony')]
    

    最后你可以在你的模板中循环它

    <table>
      <tbody>
        {% for pl in t_products %}
        <tr>
          {% for l in pl%}
             <td>{{l}}</td>
          {% endfor %} 
        </tr>
        {% endfor %}
      </tbody>
    </table>
    

    【讨论】:

      【解决方案2】:

      您可以使用pandas.DataFrame.transpose(),即,

      import pandas as pd
      from django_pandas.io import read_frame
      df = read_frame(product)
      table_html = df.transpose().to_html()
      

      您只需将table_html 字符串传递给模板;这里不需要模板逻辑。有几种方法可以将 QuerySet 转换为 DataFrame。这里我使用的是django-pandas package

      【讨论】:

        【解决方案3】:

        你可以这样做;

        <table>
          <tbody>
            <tr>
              <th>ID</th>
              {% for product in products %}<td>{{ product.id }}</td>{% endfor %}
            </tr>
            <tr>
              <th>Model</th>
              {% for product in products %}<td>{{ product.model }}</td>{% endfor %}
            </tr>
            <tr>
              <th>Manufacturer</th>
              {% for product in products %}<td>{{ product.manufacturer }}</td>{% endfor %}
            </tr>
          </tbody>
        </table>
        

        【讨论】:

        • 谢谢,但我正在寻找一种解决方案,无需像这样进行多次迭代。
        • 另一种方式,你可以用模板标签来做到这一点..但是,基本上还是一样的..
        • 因为如果它只用于记录中的 3 个字段,那么这样做是可以的,但如果它是 10 个或更多字段,那么这样做是一种不好的做法,对吧??
        【解决方案4】:

        你可以使用Bootstrap's grid system:

        <div class="row">
            <div class="col-xs-3">
                <p>id</p>
                <p>Model</p>
                <p>Manufacturer</p>
            </div>
            {% for product in products %}
            <div class="col-xs-3">
                <p>{{ product.id }}</p>
                <p>{{ product.model }}</p>
                <p>{{ product.manufacturer }}</p>
            </div>
            {% endfor %}
        </div>
        

        col-xs-3 表示该样式将适用于超小屏幕尺寸及以上(即所有屏幕),3 表示它将屏幕分成 12/3 = 4 个部分。例如,如果您想要 6 列,则必须使用 col-xs-2

        如果您不想引入 Bootstrap 的开销,那么您可以使用为 CSS3 引入的 flex boxes

        .flexcontainer {
            display: flex;
            flex-direction: row;
        }
        

        【讨论】:

        • 这是一个比较页面,会有 n 个产品,所以我不能使用引导网格系统,是的 display:flex 可能会工作,但我正在寻找使用 python 方式的解决方案:),谢谢
        猜你喜欢
        • 1970-01-01
        • 2023-04-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-31
        • 1970-01-01
        相关资源
        最近更新 更多