Vishal Taj PM
Vishal Taj PM

Reputation: 1359

How to render Django query set as column wise into html table?

Let's say my sql table looks like this..

products table

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

in django view i fetched all records from this table and passed it to template..

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})

as query_set result records comes like one after the other we can say it is following row wise but for this case in template i wanted to create an html table and the result should come like this ..

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

By looking at above example you can see data is rendered as column wise.

so please suggest me a better method in Django by which i can achieve this and also please correct me if i'm wrong as i'm beginner in Django.

Thanks in advance

Upvotes: 4

Views: 5150

Answers (4)

pandichef
pandichef

Reputation: 796

You can use pandas.DataFrame.transpose() i.e.,

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

You just pass the table_html string to the template; no template logic needed here. There are several ways to convert a QuerySet to a DataFrame. Here I'm using the django-pandas package.

Upvotes: 2

Satendra
Satendra

Reputation: 6865

Use values_list() and convert your queryset to 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')]

Now transpose this 2d matrix using zip

t_products = list(zip(*products))
# OUTPUT: [(1, 2, 3), ('ABC', 'XYZ', 'ZYX'), ('Samsung', 'LG', 'Sony')]

finally you can loop over it in your template

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

Upvotes: 6

VMatić
VMatić

Reputation: 996

You could use 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 means the style will apply from extra-small screen sizes and upwards (i.e. all screens) and 3 means it will split the screen into 12/3 = 4 parts. If you wanted, for example, 6 columns then you'd have to use col-xs-2.

If you don't want to bring in the overhead of Bootstrap then you could use flex boxes which were brought in for CSS3.

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

Upvotes: 0

binpy
binpy

Reputation: 4194

You can do it with this;

<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>

Upvotes: 0

Related Questions