34

I am trying to use django with pandas for data analysis. There seem to be no simple step by step tutorial on this. All the ones i have seen online just explain how to write the code in your django views.py file but none shows how to display the final product in the browser.

Here is the code in my views.py

def index2(request):
    qs = Product.objects.all()
    df = read_frame(qs)
    html= df.to_html
    return HttpResponse(html)

but this does not work. Any detailed help will be appreciated. Please dont just point me to some documentation. In fact, most of django's documentation is not written in simple plain english --- it is even more confusing to some of us. Thank you.

3
  • 2
    What do you mean by doesn't work? Doesn't work as expected, or just doesn't work full stop? dataframe's .to_html function just gives you a bare html table, not a webpage,dependent on the browser you may need to add proper tags around it using a django template. What does print(Product.objects.all().count()) output? Commented Oct 5, 2016 at 22:55
  • I mean nothing shows in my browser, no table (nothing). I will try the print statement and see the output thank you. Commented Oct 9, 2016 at 6:35
  • 7
    html=df.to_html() would have done the job for you. The () was required. Commented May 10, 2019 at 4:28

4 Answers 4

31

Here is a minimal but elegant solution using Django_Pandas and an 'extended Bootstrap table' (https://github.com/wenzhixin/bootstrap-table)

The elegance comes from the ability to export a Pandas DataFrame to JSON, and for the Bootstrap Table script to consume that JSON content.

The HTML table is written for us, we don't need to worry about it (look below where we just include the 'table' tag without writing the rows ourselves, or even a for loop.) And it's interactive. And Bootstrap makes it look pretty.

requirements: Bootstrap, JQuery, Django_Pandas, wenzhixin/bootstrap-table

models.py

from django.db import models
from django_pandas.managers import DataFrameManager

class Product(models.Model):
  product_name=models.TextField()
  objects = models.Manager()
  pdobjects = DataFrameManager()  # Pandas-Enabled Manager 

views.py

from models import Product
def ProductView(request):
  qs = Product.pdobjects.all()  # Use the Pandas Manager
  df = qs.to_dataframe()
  template = 'product.html'

  #Format the column headers for the Bootstrap table, they're just a list of field names, 
  #duplicated and turned into dicts like this: {'field': 'foo', 'title: 'foo'}
  columns = [{'field': f, 'title': f} for f in Product._Meta.fields]
  #Write the DataFrame to JSON (as easy as can be)
  json = df.to_json(orient='records')  # output just the records (no fieldnames) as a collection of tuples
  #Proceed to create your context object containing the columns and the data
  context = {
             'data': json,
             'columns': columns
            }
  #And render it!
  return render(request, template, context)

product.html

<script src='/path/to/bootstrap.js'>
<script src='/path/to/jquery.js'>
<script src='/path/to/bootstrap-table.js'>
<script src='/path/to/pandas_bootstrap_table.js'>
<table id='datatable'></table>
<!-- Yep, all you need is a properly identified
     but otherwise empty, table tag! -->

pandas_bootstrap_table.js

$(function() {
  $('#datatable')({
    striped: true,
    pagination: true,
    showColumns: true,
    showToggle: true,
    showExport: true,
    sortable: true,
    paginationVAlign: 'both',
    pageSize: 25,
    pageList: [10, 25, 50, 100, 'ALL'],
    columns: {{ columns|safe }},  // here is where we use the column content from our Django View
    data: {{ data|safe }}, // here is where we use the data content from our Django View. we escape the content with the safe tag so the raw JSON isn't shown.
  });
});
Sign up to request clarification or add additional context in comments.

9 Comments

I haven't edited your answer as you may be using functionality that I'm not familiar with, but I believe your syntax in your js should be: $('#datatable.pandas').bootstrapTable({. That being said, I don't think the functionality you're using is in bootstrap. There is a separate add on called bootstraptables that looks to have the same syntax?
K.B. You are correct at least about the third-party tool I previously neglected to mention: github.com/wenzhixin/bootstrap-table. Updated accordingly.
K.B. I think here for simplicity I could remove the table class and just hard-code it to the ID like so: $('#datatable')({
Thank you so much for taking your time to explain everything so clearly. I will try it out this weekend. Thank you.
How can i use this method if i had a dataframe in views and not in models ?
|
25

to_html is a function, you have to call it.

def index2(request):
    df = read_frame(Product.objects.all())
    return HttpResponse(df.to_html())

3 Comments

It doesn't work as expected. It adds <table> tags, but doesn't display correctly in template.
@MehdiZare, you have to add the safe filter to context: {{df|safe}}
This worked with me, and the look for the df as a table been fixed by adding ""{{your_df_data|safe}}"" into the template....Thanks to Braulio.
4

I read almost all answers here but I think I might have a discovered an easier way. My problem was to display multiple dataframes in a html page. This is what worked for me:

views.py

f = pd.read_csv("C:\pythprograms\hoe\shop\static\shop\mytest.csv",encoding= 'unicode_escape')
    
    geeks_object = df.to_html(classes='data', header="true")
    params={'geek': geeks_object}
  
    return render(request, 'shop/demo.html',params)

demo.html

<html>
    <body>
        <table>{{geek|safe}}</table>
    </body>
</html>

Comments

3

#app/models.py

    from django.db import models
    class Consumer(models.Model):
        username = models.CharField(max_length=100, null=True)
        phone = models.BigIntegerField(null=True)
        first_name = models.CharField(max_length=100, null=True)
        last_name = models.CharField(max_length=100, null=True)
        
        def __str__(self):
            return self.first_name

#app/views.py

    from django.shortcuts import render
    import pandas as pd 
    from .models import Consumer
    import json 
    def ConsumerView(request): 
        qs = Consumer.objects.all()
        consumers = [{"UserName":x.username,"FirstName":x.first_name,"LastName":x.last_name} for x in qs]
         
        df = pd.DataFrame(consumers)
      
        # parsing the DataFrame in json format. 
        json_records = df.reset_index().to_json(orient ='records') 
        data = [] 
        data = json.loads(json_records) 
        context = {'d': data} 
        return render(request, "CR.html", context)

#app/urls.py

from django.urls import path
from .views import ConsumerView
urlpatterns = [
    path('',ConsumerView, name='CR'),
]

#templates/CR.html

<!DOCTYPE html> 
<html lang="en"> 
<head> 
<title>Django-Pandas-Template</title> 
<meta charset="utf-8"> 
<meta name="viewport" content="width=device-width, initial-scale=1"> 
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"> 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script> 
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script> 
</head> 
<body> 

<div class="container"> 
<h2 class="text-center"><u>Django models --> Pandas DataFrame --> render to --> Templates(.html)  </u></h2><br>          
<table class="table table-dark table-striped"> 
    <thead> 
    <tr> 
        <th>User Name</th> 
        <th>First Name</th> 
        <th>Last Name</th> 
        
    </tr> 
    </thead> 
    <tbody> 
    <!-- jinja2 Technique -->
    {% if d %} 
    {% for i in d %} 
    <tr> 
        <td>{{i.UserName}}</td> 
        <td>{{i.FirstName}}</td> 
        <td>{{i.LastName}}</td> 
        
    </tr> 
    {% endfor %} 
    {% endif %} 
    </tbody> 
</table> 
</div> 

</body> 
</html> 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.