Sunday, February 17, 2013

Simple employee table with OpenStack Horizon DataTable module

I was working on OpenStack dashboard (aka Horizon) few past few months and I will share a simple way to build your data tables based on Horizon.
To give a brief introduction of Horizon, it is the official dashboard project of OpenStack, the cloud operating system. Horizon is a python Django application. It provides pre-defined modules for common web application requirements like tabs, workflow, table etc. From Grizzly release onward Horizon modules are separated from OpenStack specific code. It allows one to use Horizon modules independently.

To build a data table in Horizon you need to simply create a model class for your data. The important thing to remember here is that the class must have an "id" attribute. Horizon will build rows based on this id. It can be alpha numeric also. Though it is not mandatory to display the id column in the table, you can still have it. Below is the data model for my Employee table -

class Employee:
    """
    Employee class represents the employee data
    """

    def __init__(self, emp_id, name, addr, salary):
        self.id = emp_id
        self.name = name
        self.addr = addr
        self.salary = salary
 
The employee class has 4 attributes - id, name, address and the salary. Each of these attributes can be displayed in a column of our Horizon DataTable. I use below code in my views.py


from horizon import tables
from .tables import TabledisplayTable

class IndexView(tables.DataTableView):
    table_class = TabledisplayTable
    template_name = 'project/tabledisplay/index.html'

    def get_data(self):
        strobj = '[{"id": 111, "name": "emp1", "salary": 1000, "addr": "kolkata"}, {"id": 222, "name": "emp2", "salary": 5000, "addr": "bangalore"}]'
        instances = json.loads(strobj)
        ret = []
        for inst in instances:
            ret.append(Employee(inst['id'], inst['name'], inst['addr'], inst['salary']))
        return ret
 

We need to create a tables.py with TabledisplayTable class which allows us to map the columns to model attributes. Like this -

from horizon import tables
from django.utils.translation import ugettext_lazy as _

class TabledisplayTable(tables.DataTable):
    name = tables.Column("name",
                         verbose_name=_("Employee Name"))
    salary = tables.Column("salary", verbose_name=_("Salary in Rs"))
    addr = tables.Column("addr",
                         verbose_name=_("Address"))

    class Meta:
        name = "emptable"
        verbose_name = _("Employee Table")
 

Finally we need a Django template to render this table. I have used the following code -
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Table Display" %}{% endblock %}

{% block page_header %}
  {% include "horizon/common/_page_header.html" with title=_("Employee Table Display") %}
{% endblock page_header %}

{% block main %}
  {{ table.render }}
{% endblock %}
 

This should create the Employee table with 2 rows using Horizon DataTable module. Try it out.