Generic List View with Django Tables

I have been working on a client's Django project this week.

This project is a complete re-write of the customer front-end website. The current system utilizes function based views and misses out on many of Django's best practices.

Not to mention, I'm not a huge fan of Function Based Views (FBV's) in Django.

My notepad lists the new website implementation requirements for the revised consumer portal. Those requirements are, in no particular order:

  1. Utilize generic class based views in Django
  2. The resulting generic ListView must be a sortable table
  3. Link multiple table columns to different routes by pk
  4. Write simple idiomatic Python that is easily maintained.

I prefer Django's class based views (CBV's) over function based views for several reasons. Most websites that I design are data-driven and contain typical workflows for managing client data. These include generic TemplateView, ListView, DetailView, CreateView, UpdateView, FormView and DeleteView.

Benefits of Class-Based Views
  1. Organization of code. A single CBV can contain multiple functions; whereas a FBV only renders the methods of the function for the specific view that is called by the router.
  2. A majority of the boiler plate code is bypassed for Django's generic views making development fast, simple and feature rich.
  3. Calling a CreateView and binding the form class is less than 10 lines of code rather than a much more verbose FBV.
  4. CBV's reduce code repetition and increases code reuse by the way of mixins.
  5. Django braces make my life much easier.
  6. Using Django's ORM let's the framework do all the heavy lifting freeing me up to concentrate on the features of the application.
Django Tables

I have used Django Tables in the past and this is an extremely straight-forward approach to creating a list view data table with a simple one-line statement, like...

{% render table %}

Get django_tables2 and install via pip...

pip install django-tables2  

Then add it to the list of apps in settings.py.

INSTALLED_APPS = (  
    ...
    django_tables2
    ...
)

The page I'm working on in the consumer portal requires a Customer list with links to the customer's detail information, address details, invoices and private account details and banking.

I handle all of these requirements in my views.py.

I could use a separate method for the get_queryset() function, but I have learned that it's just as easy to embed my queryset call inside of the table statement in the get context data function.

table = CustomerTable(Customer.objects.filter(self.kwargs['company']).order_by('-pk'))  

Don't forget to create tables.py to set up the table params:

Now, I can simply render the table within my template with the statement from above

{% render table %}
  • I am no longer rendering the table in this way. Please refer to the template layout below for more information.

and I get a nicely formatted table with sort features and pagination.

Classy Customer View

Wrapping Up

It should also be mentioned... the magic of Django's Generic CBV's comes with a cost. While you can save literally hundreds of hours of programmer development time, obfuscation of the complexity of the code hides what is going on "behind the scenes." While using FBV's, the developer must create explicit behaviors for every function including form processing and passing variables within the request context. The result is simple, easy to understand code that is easily maintained by a team of devs.

A terrific resource for learning all about Django CBV's can be found at Classy Class-Based Views

I love me some Django!

Edit: 5-16-2016
As requested, I am adding both the models.py and the template customers.html to this post to complete the source.

models.py

customers.html

Craig Derington

Veteran full stack web dev focused on deploying high-performance, responsive, modern web applications using Python, NodeJS, Django, Flask, MongoDB and MySQL.

comments powered by Disqus