Skip to content
klipstein edited this page Jun 7, 2012 · 1 revision

Quick walk through for using the datagrid templatetag

Install Dojango

See getting started guide

Create Project and App

From your command line prompt create a project and an app within

 django-admin.py startproject test_dojango
 cd test_dojango
 python manage.py startapp myapp

and make the following changes to settings.py:

INSTALLED_APPS = (
    # ...
    'dojango','myapp',

MIDDLEWARE_CLASSES = ( 
   # ...
   'dojango.middleware.DojoCollector', # not DojoAutoRequireMiddleware anymore!

To deliver the media files you also have to add the URL definitions of dojango to your main URL defintion file (test_dojango/urls.py):

urlpatterns = patterns('',
    # ...
    (r'^dojango/', include('dojango.urls')),
)

Create Models

For the sake of this walk through we will create a couple simple models in myapp.models:

class Test(models.Model):
    name = models.CharField(max_length=32)
    desc = models.CharField(max_length=64)

    def result_totals(self): 
        qset = Result.objects.filter(test=self)
        total = qset.count()
        if total==0: return (0,0)
        accm = qset.filter(status="pass").count()
        return (total,accm)
    result_totals.short_description= "Total(<font color=green>Passed</font>)"

class Result(models.Model):
    name = models.CharField(max_length=15)
    status = models.CharField(max_length=4)
    test = models.ForeignKey(Test)

Add them to the grant list for dojango in your setting.py. The contents of this tuple can be 'app.model' to allow access to a specific model, or 'app' to allow access to all models within that app or 'model' for any model whose name matches.

DOJANGO_DATAGRID_ACCESS = (
  'myapp.Test',
  'myapp.Result',
)

To generate data so our datagrid has something to show here is a quick function to add test data.

from random import choice, randint, sample
import string

from myapp.models import Result, Test

def create_results(x):
    for tests in xrange(x):
        test = Test(name="test%s"%tests, desc="desc for %s"%tests)
        test.save()
        for i in xrange(randint(1,5)):
            r = Result(test=test)
            r.name =  ''.join(sample(string.letters, randint(4,10)))
            r.status = choice(("pass","fail"))
            r.save()

Create the view and template

in urls we add to a default path:

urlpatterns = patterns('',
  # ...
  (r'^dojango/', include('dojango.urls')),
  (r'','myapp.views.index')
)
then within myapp.views we add a function to handle the request:
from django.shortcuts import render_to_response

def index(request):        
    context = {}
    return render_to_response("list_tests.html", context)

Finally we create a template to render containing our datagrid:

{% extends "dojango/base.html" %}
{% load dojango_grid %}
{% block dojango_page_title %} Testing datagrid {% endblock %}

{% block dojango_content %}
<H1>Lists:</H1>
<div style="height:100px; width:400px">
    {% simple_datagrid myapp Test %}
</div>
{% endblock %}

More advanced options

Then in settings.py you can change the Dojo theme:

DOJANGO_DOJO_THEME = "soria"

I will use soria for the rest of this walk through. You notice the use of the simple_datagrid which is the equivalent the datagrid tag with no options.

{% datagrid myapp Test %}
{% enddatagrid %}

within the contents of this tag (which will be rendered under the context passed by the views.index function) will be a option=value list, one per line. The contents is comparable to that of the Admin class defined in the models when customizing the admin interface, i.e.

class Test(models.Model):
    name = models.CharField(max_length=32)
    desc = models.CharField(max_length=64)

    class Admin:
        list_display = ('name', 'desc')

would be used to limit the admin change list to only display the name and the desc fields. To do the equivalent within the template tag:

{% datagrid myapp Test %}
 list_display = ('name','desc')
{% enddatagrid %}

Since this is defined in the template however we can create multiple instances of the Test models grid with different options. Also since this is within the template there exist options to define how to display them:

  {% datagrid myapp Test %}
   list_display = ('name','desc')
   width = "130px"
   column_width = {'name':'35px'}
  {% enddatagrid %}

  <div style="margin-top:20px">
      {% datagrid myapp Test %}
       list_display = ('id','name','result_totals')
       width = "350px"
       height= "170px"
      {% enddatagrid %}
  </div>

A point to this is that the result_totals is a function of the model and not a field, but when added to the list_display tuple or list it will added. The different header is from the functions "short_description" which is the same as for the Admin interface. They can also be specified within the template with the label option.

      {% datagrid myapp Test %}
         list_display = ('id','name','result_totals')
         width = "350px"
         height= "170px"
         label = {'name': 'Test Name'}
      {% enddatagrid %}
There will be a error if trying to sort on the result_totals column, simply because a query set cannot be ordered by a function of model. You can disable sorting on columns with the "nosort" option.
      {% datagrid myapp Test %}
         list_display = ('id','name','result_totals')
         width = "350px"
         height= "170px"
         label = {'name': 'Test Name'}
         nosort= ['result_totals']
      {% enddatagrid %}

it was done above with a list instead of a tuple this, but they are interchangeable.

Live Search

You can specify a list of fields for the search option that will be added (OR'd together) to the where clause. If the value is a field it will look for an exact match, but you can also specify operators. i.e.

search = ('name', 'desc__contains')

will return models whose name is the same as the search or whose desc contains that is within the search field (other operators like gt,lt,lte,gte,startswith and endswith will work also). The queryreadstore will be updated on every keyup event in the search field.

      {% datagrid myapp Test %}
         list_display = ('id','name','result_totals')
         width = "350px"
         height= "170px"
         label = {'name': 'Test Name'}
         nosort= ['result_totals']
         search= ('name__contains','desc__contains')
      {% enddatagrid %}

Options

list_display list or tuple of model attributes (model fields or model functions). defaults to all of the sql fields of the model
column_width dict with model attribute:width
default_width default width if not specified by column_width. defaults to "auto"
width width of the datagrid, defaults to "100%"
height height of datagrid, defaults to "100%"
id id of datagird, optional but useful to if planning on using dojo.connect to the grid.
label dict of attribute:label for header. (other ways exist of setting these)
query way to specify conditions for the table. i.e. to only display elements whose id>10: query={ 'id__gt':10 }
search list or tuple of fields to query against when searching
nosort fields not to sort on
formatter dict of attribute:js formatter function