Search code examples
djangopython-3.xdjango-tables2

display data in tables in django


I have narrowed down to the following , if anyone can help me pointing out how i can convert the following into table view that would be awesome. Following html is extended from the base.html

{% block page_content %}


<h1>Projects</h1>
<div class="row">
{% for project in projects %}
    <div class="col-md-4">
       <div class="card mb-2">
            <img class="card-img-top" src="{% static project.image %}">
            <div class="card-body">
                <h5 class="card-title">{{ project.title }}</h5>
                <p class="card-text">{{ project.description }}</p>
                <a href="{% url 'project_detail' project.pk %}"
                   class="btn btn-primary">
                    Read More
                </a>

            </div>
        </div>
    </div>
    {% endfor %}
</div>
{% endblock %}

Need help with displaying data in gridview . I m new to all this. I m able to read and display the data on a page from mongodb but need to display in a table.

million $ question for me now is where should i be adjusting the following snippet in my code to give me gridview

<table>
    <tr>
        <th>Field 1</th>
        <th>Field N</th>
    </tr>
    {% for item in query_results %}
    <tr> 
        <td>{{ item.field1 }}</td>
        ...
        <td>{{ item.fieldN }}</td>
    </tr>
    {% endfor %}
</table>

My urls.py

from django.urls import path
from .import views

urlpatterns = [
    path("",views.project_index, name = "project_index"),
    path ("<project_detail>/",views.project_detail, name = "project_detail"),
    #path("<int:pk>/", views.project_detail, name = "project_detail"),
]

My model.py

from django.db import models

# Create your models here.
class Project(models.Model):
    title = models.CharField(max_length=100,primary_key=True)
    desc = models.CharField(max_length=100)
    urls = models.CharField(max_length=100)
    #image = models.FilePathField(path="/img")

    class Meta:
        db_table = "spiderCollection1"

additional tables.py

import django_tables2 as tables
from .models import Project
import itertools

class ProjectTable(tables.Table):
    class Meta:
        model = Project
        template_name = "django_tables2/bootstrap.html"
        title = tables.Column("title")
        desc = tables.Column("desc")
        urls = tables.Column("urls")

following is views.py

from django_tables2 import SingleTableView
from django.shortcuts import render
from projects.models import Project
from projects.tables import ProjectTable

# Create your views here.
class ProjectListView(SingleTableView):
    model = Project
    table_class = ProjectTable
    template_name = '/projects.html'

def project_index(request):
    projects = Project.objects.all()
    context = {
        "projects":projects
    }
    return render (request, 'project_index.html',context)
    #return render (request, 'project_index.html',locals())

def project_detail(request, pk):
    #project = Project.objects.get(pk=pk)
    project = Project.objects.all()
    context = {
        "project": project
        #'personal_portfolio':project
    }
    return render(request, 'project_detail.html',context)

my main base.html

<nav class="navbar navbar-expand-lg navbar-light bg-light">
    <div class="container">
        <a class="navbar-brand" href="{% url 'project_index' %}">Portfolio</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>

        <div class="collapse navbar-collapse" id="navbarSupportedContent">
          <ul class="navbar-nav mr-auto">

              <li class="nav-item active">
              <a class="nav-link" href="{% url 'project_index' %}">Home</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Blog</a>
            </li>
          </ul>
        </div>
    </div>

    <!--<style>
        h1 {
            border: 5px solid red;
            }

        h2 {
            border: 4px dotted blue;
            }
        div {
            border: double;
            }
      </style>
      -->


</nav>

<div class="container">
    {% block page_content %}
    {% endblock %}
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>

and now project_index.html

{% extends "base.html" %}
{%load render_table from django_tables %}
{% load static %}
{% block page_content %}


<h1>Projects</h1>
<div class="row">
{% for project in projects %}
    <div class="col-md-4">
       <div class="card mb-2">
            <img class="card-img-top" src="{% static project.image %}">
            <div class="card-body">
                <h5 class="card-title">{{ project.title }}</h5>
                <p class="card-text">{{ project.description }}</p>
                <a href="{% url 'project_detail' project.pk %}"
                   class="btn btn-primary">
                    Read More
                </a>
            </div>
        </div>
    </div>


    {% endfor %}
</div>
{% endblock %}

Solution

  • If the goal is to display a table without using the django-table2 package follow the first part of the answer. If the goal is to use django-table2 then jump to Part II:

    Part I

    Based on your colde, let us use the example snippet, and edit it in order to display your project data in an HTML table...

    Starting with your project_index.html, we need create the skeleton of the html table using <table>, <thead>, <tbody> and <th> tags, and then to loop over the passed projects context variable and add entries to the table using the <td> tag. And because you are using the bootstrap framework, we will need the row and the column divss to display the table correctly.

    {% extends "base.html" %}
    {% load static %}
    
    {% block page_content %}
    
    <h1>Projects</h1>
    <div class="row">
        <div class="col-md-4"> 
            <table class="table table-striped table-hover">
            <thead>
                <th>#</th>
                <th>title</th>
                <th>description</th>
            </thead>
            <tbody>
            {% for project in projects %}
               <td><strong>{{ forloop.counter }} </strong></td>
               <td><strong>{{ project.title}</strong></td>
               <td>{{ project.description} <a href="{% url 'project_detail' project.pk %}" class="btn btn-primary">Read More</a> </td>
            {% endfor %}
            </tbody>
            </table>
        <div>
    </div>
    {% endblock %}
    

    Make sure that your url.py points to the function project_index

    To learn more check:

    Part II

    Django-table2 is a package that provides an app and middleware to generate html tables. In order to use it in your app make the following changes to your project_index.html:

    {% extends "base.html" %}
    {% load render_table from django_tables %}
    {% load static %}
    {% block page_content %}
    
    
    <h1>Projects</h1>
    <div class="row">
        <div class="col-md-4">
        {% render_table projects %}
        </div>
    </div>
    {% endblock %}
    

    The code above will use the html template provided by django-table2 for rendering tables, defined in your class ProjectTable

    class ProjectTable(tables.Table):
        class Meta:
            model = Project
            template_name = "django_tables2/bootstrap.html"  
            ...
    

    If you want to use a custom rendering you will need to set the template_name of the ProjectTable to your custom.html:

     class ProjectTable(tables.Table):
        class Meta:
            model = Project
            template_name = "custom.html"  
            ...
    

    Now create custom.html and add the code that will actually iterate over the items of the projects context variable. Maybe something like this (copied from the django_tables2/semantic.html)... Make changes you want to this template.

    {% load django_tables2 %}
    {% load i18n %}
    {% block table-wrapper %}
    <div class="ui container table-container">
        {% block table %}
            <table {% render_attrs table.attrs class="ui celled table" %}>
                {% block table.thead %}
                {% if table.show_header %}
                    <thead {{ table.attrs.thead.as_html }}>
                        <tr>
                        {% for column in table.columns %}
                            <th {{ column.attrs.th.as_html }}>
                                {% if column.orderable %}
                                    <a href="{% querystring table.prefixed_order_by_field=column.order_by_alias.next %}">{{ column.header }}</a>
                                {% else %}
                                    {{ column.header }}
                                {% endif %}
                            </th>
                        {% endfor %}
                        </tr>
                    </thead>
                {% endif %}
                {% endblock table.thead %}
                {% block table.tbody %}
                    <tbody {{ table.attrs.tbody.as_html }}>
                    {% for row in table.paginated_rows %}
                        {% block table.tbody.row %}
                        <tr {{ row.attrs.as_html }}>
                            {% for column, cell in row.items %}
                                <td {{ column.attrs.td.as_html }}>{% if column.localize == None %}{{ cell }}{% else %}{% if column.localize %}{{ cell|localize }}{% else %}{{ cell|unlocalize }}{% endif %}{% endif %}</td>
                            {% endfor %}
                        </tr>
                        {% endblock table.tbody.row %}
                    {% empty %}
                        {% if table.empty_text %}
                        {% block table.tbody.empty_text %}
                        <tr><td colspan="{{ table.columns|length }}">{{ table.empty_text }}</td></tr>
                        {% endblock table.tbody.empty_text %}
                        {% endif %}
                    {% endfor %}
                    </tbody>
                {% endblock table.tbody %}
                {% block table.tfoot %}
                <tfoot {{ table.attrs.tfoot.as_html }}>
                    {% if table.has_footer %}
                    <tr>
                    {% for column in table.columns %}
                        <td {{ column.attrs.tf.as_html }}>{{ column.footer }}</td>
                    {% endfor %}
                    </tr>
                    {% endif %}
                    {% block pagination %}
                        {% if table.page and table.paginator.num_pages > 1 %}
                        <tr>
                        <th colspan="{{ table.columns|length }}">
                            <div class="ui right floated pagination menu">
                                {% if table.page.has_previous %}
                                    {% block pagination.previous %}
                                    <a href="{% querystring table.prefixed_page_field=table.page.previous_page_number %}" class="icon item">
                                        <i class="left chevron icon"></i>
                                    </a>
                                    {% endblock pagination.previous %}
                                {% endif %}
    
                                {% if table.page.has_previous or table.page.has_next %}
                                    {% block pagination.range %}
                                        {% for p in table.page|table_page_range:table.paginator %}
                                            {% if p == '...' %}
                                                <a href="#" class="item">{{ p }}</a>
                                            {% else %}
                                                <a href="{% querystring table.prefixed_page_field=p %}" class="item {% if p == table.page.number %}active{% endif %}">
                                                    {{ p }}
                                                </a>
                                            {% endif %}
                                        {% endfor %}
                                    {% endblock pagination.range %}
                                {% endif %}
    
                                {% if table.page.has_next %}
                                    {% block pagination.next %}
                                    <a href="{% querystring table.prefixed_page_field=table.page.next_page_number %}" class="icon item">
                                        <i class="right chevron icon"></i>
                                    </a>
                                    {% endblock pagination.next %}
                                {% endif %}
                            </div>
                        </th>
                        </tr>
                        {% endif %}
                    {% endblock pagination %}
                </tfoot>
                {% endblock table.tfoot %}
            </table>
        {% endblock table %}
    </div>
    {% endblock table-wrapper %}
    

    Here make sure your urls.py includes:

    ...
    path("projects/", ProjectListView.as_view())
    ...
    

    for more refer to: