Added SingleTableMixin that makes adding a table to a view trivially easy. Partially...
authorBradley Ayers <bradley.ayers@gmail.com>
Thu, 2 Jun 2011 13:01:48 +0000 (23:01 +1000)
committerBradley Ayers <bradley.ayers@gmail.com>
Thu, 2 Jun 2011 13:01:48 +0000 (23:01 +1000)
django_tables/views.py [new file with mode: 0644]
docs/index.rst

diff --git a/django_tables/views.py b/django_tables/views.py
new file mode 100644 (file)
index 0000000..886ffe3
--- /dev/null
@@ -0,0 +1,81 @@
+from django.core.exceptions import ImproperlyConfigured
+from django.views.generic.base import TemplateResponseMixin
+from django.views.generic.list import BaseListView
+
+
+class SingleTableMixin(object):
+    """
+    Adds a Table object to the context. Typically used with
+    ``TemplateResponseMixin``.
+
+    :param table_class: table class
+    :type table_class: subclass of ``django_tables.Table``
+
+    :param table_data: data used to populate the table
+    :type table_data: any compatible data source
+
+    :param context_table_name: name of the table's template variable (default:
+        "table")
+    :type context_table_name: ``string``
+
+    This mixin plays nice with the Django's ``MultipleObjectMixin`` by using
+    ``get_queryset()`` as a fallback for the table data source.
+    """
+    table_class = None
+    table_data = None
+    context_table_name = None
+
+    def get_table(self):
+        """
+        Return a table object to use. The table has automatic support for
+        sorting and pagination.
+        """
+        table_class = self.get_table_class()
+        table = table_class(self.get_table_data(),
+                            order_by=self.request.GET.get("sort"))
+        table.paginate(page=self.request.GET.get("page", 1))
+        return table
+
+    def get_table_class(self):
+        """
+        Return the class to use for the table.
+        """
+        if self.table_class:
+            return self.table_class
+        raise ImproperlyConfigured(u"A table class was not specified. Define"
+                                   u"%(cls)s.table_class"
+                                   % {"cls": self.__class__.__name__})
+
+    def get_context_table_name(self, table):
+        """
+        Get the name to use for the table's template variable.
+        """
+        return self.context_table_name or "table"
+
+    def get_table_data(self):
+        """
+        Return the table data that should be used to populate the rows.
+        """
+        if self.table_data:
+            return self.table_data
+        elif hasattr(self, "get_queryset"):
+            return self.get_queryset()
+        raise ImproperlyConfigured(u"Table data was not specified. Define "
+                                   u"%(cls)s.table_data"
+                                   % {"cls": self.__class__.__name__})
+
+    def get_context_data(self, **kwargs):
+        """
+        Overriden version of ``TemplateResponseMixin`` to inject the table into
+        the template's context.
+        """
+        context = super(SingleTableMixin, self).get_context_data(**kwargs)
+        table = self.get_table()
+        context[self.get_context_table_name(table)] = table
+        return context
+
+
+class SingleTableView(SingleTableMixin, TemplateResponseMixin, BaseListView):
+    """
+    Generic view that renders a template and passes in a ``Table`` object.
+    """
index 5915148765e57e9622d90325cb556ace89fe4968..d6e6a3f89fc00d94f7f89bd3845e8e35ff38bda0 100644 (file)
@@ -615,6 +615,65 @@ which can be iterated over:
     </table>
 
 
+Class Based Generic Mixins
+==========================
+
+Django 1.3 introduced `class based views`__ as a mechanism to reduce the
+repetition in view code. django-tables comes with a single class based view
+mixin: ``SingleTableMixin``. It makes it trivial to incorporate a table into a
+view/template, however it requires a few variables to be defined on the view:
+
+- ``table_class`` –- the table class to use, e.g. ``SimpleTable``
+- ``table_data`` (or ``get_table_data()``) -- the data used to populate the
+  table
+- ``context_table_name`` -- the name of template variable containing the table
+  object
+
+.. __: https://docs.djangoproject.com/en/1.3/topics/class-based-views/
+
+For example:
+
+.. code-block:: python
+
+    from django_tables.views import SingleTableMixin
+    from django.generic.views.list import ListView
+
+
+    class Simple(models.Model):
+        first_name = models.CharField(max_length=200)
+        last_name = models.CharField(max_length=200)
+
+
+    class SimpleTable(tables.Table):
+        first_name = tables.Column()
+        last_name = tables.Column()
+
+
+    class MyTableView(SingleTableMixin, ListView):
+        model = Simple
+        table_class = SimpleTable
+
+
+The template could then be as simple as:
+
+.. code-block:: django
+
+    {% load django_tables %}
+    {% render_table table %}
+
+Such little code is possible due to the example above taking advantage of
+default values and ``SimpleTableMixin``'s eagarness at finding data sources
+when one isn't explicitly defined.
+
+.. note::
+
+    If you want more than one table on a page, at the moment the simplest way
+    to do it is to use ``SimpleTableMixin`` for one table, and write the
+    boilerplate for the other yourself in ``get_context_data()``. Obviously
+    this isn't particularly elegant, and as such will hopefully be resolved in
+    the future.
+
+
 API Reference
 =============