updated some docstrings, fixed issue #16, added some tests for i18n support
authorBradley Ayers <bradley.ayers@gmail.com>
Sat, 9 Jul 2011 22:21:49 +0000 (08:21 +1000)
committerBradley Ayers <bradley.ayers@gmail.com>
Sat, 9 Jul 2011 22:21:49 +0000 (08:21 +1000)
django_tables2/columns.py
django_tables2/tables.py
tests/columns.py
tests/models.py
tests/testapp/models.py

index e711d7178d33d91c91e4ac0b1f9a9fc3cf993d80..d597f4a684609e3399d3a876bca48a1c75c91962 100644 (file)
@@ -17,8 +17,10 @@ class Column(object):
     :class:`Column` objects control the way a column (including the cells that
     fall within it) are rendered.
 
-    :param verbose_name: A pretty human readable version of the column name.
-        Typically this is used in the header cells in the HTML output.
+    :param verbose_name: A human readable version of the column name.
+        Typically this is used in the header cells in the HTML output. (But if
+        you're writing your own template, use ``.header`` rather than
+        ``.verbose_name``)
 
     :type accessor: :class:`basestring` or :class:`~.utils.Accessor`
     :param accessor: An accessor that describes how to extract values for this
@@ -96,7 +98,7 @@ class Column(object):
         """
         return self.verbose_name
 
-    def render(self, value, **kwargs):
+    def render(self, value):
         """
         Returns the content for a specific cell.
 
@@ -297,10 +299,11 @@ class TemplateColumn(Column):
 
 class BoundColumn(object):
     """
-    A *runtime* version of :class:`.Column`. The difference between
-    ``BoundColumn`` and ``Column``, is that ``BoundColumn`` objects are of the
-    relationship between a ``Column`` and a :class:`.Table`. This means that it
-    knows the *name* given to the ``Column``.
+    A *run-time* version of :class:`.Column`. The difference between
+    ``BoundColumn`` and ``Column``, is that ``BoundColumn`` objects include the
+    relationship between a ``Column`` and a :class:`.Table`. In practice, this
+    means that a ``BoundColumn`` knows the *"variable name"* given to the
+    ``Column`` when it was declared on the ``Table``.
 
     For convenience, all :class:`.Column` properties are available from this
     class.
@@ -405,11 +408,12 @@ class BoundColumn(object):
         relationship turns from ORM relationships to object attributes [e.g.
         person.upper should stop at person]).
         """
-        # Favor an explicit verbose_name
+        # Favor an explicit defined verbose_name
         if self.column.verbose_name:
             return self.column.verbose_name
 
-        # Reasonable fallback
+        # This is our reasonable fallback, should the next section not result
+        # in anything useful.
         name = self.name.replace('_', ' ')
 
         # Perhap use a model field's verbose_name
index 3bd4c56cfe45d3f14e4665c05d7092167ff3fc54..abe49de602f4462f9ab9f44d8056a26229f3b0b6 100644 (file)
@@ -161,7 +161,11 @@ class DeclarativeColumnsMetaclass(type):
         attrs["base_columns"] = SortedDict(parent_columns)
         # Possibly add some generated columns based on a model
         if opts.model:
-            extra = SortedDict(((f.name, Column()) for f in opts.model._meta.fields))
+            # We explicitly pass in verbose_name, so that if the table is
+            # instantiated with non-queryset data, model field verbose_names
+            # are used anyway.
+            extra = SortedDict(((f.name, Column(verbose_name=f.verbose_name))
+                                for f in opts.model._meta.fields))
             attrs["base_columns"].update(extra)
         # Explicit columns override both parent and generated columns
         attrs["base_columns"].update(SortedDict(columns))
index 8dd7cb618d86f79b2c2375a67cca350162a33e0a..8767be9168f754c21effa2dbee0899c4edfe77dd 100644 (file)
@@ -8,10 +8,13 @@ from django.core.exceptions import ImproperlyConfigured
 import django_tables2 as tables
 from django_tables2 import utils, A
 from .testapp.models import Person
+from django.utils.translation import ugettext_lazy
+from django.utils.translation import ugettext
 
 
 general = Tests()
 
+
 @general.test
 def sortable():
     class SimpleTable(tables.Table):
@@ -33,6 +36,21 @@ def sortable():
     Assert(SimpleTable([]).columns['name'].sortable) is True
 
 
+@general.test
+def translation():
+    """
+    Tests different types of values for the ``verbose_name`` property of a
+    column.
+    """
+    class TranslationTable(tables.Table):
+        normal = tables.Column(verbose_name=ugettext("Normal"))
+        lazy = tables.Column(verbose_name=ugettext("Lazy"))
+
+    table = TranslationTable([])
+    Assert("Normal") == table.columns["normal"].header
+    Assert("Lazy") == table.columns["lazy"].header
+
+
 @general.test
 def sequence():
     """
index af311262e97c7388f3aca3eb3b92c9ac66f8a662..54d6b87869f87f75df3eff46241955fc4db1cc83 100644 (file)
@@ -100,6 +100,8 @@ def verbose_name():
         r1 = tables.Column(accessor='occupation.region.name')
         r2 = tables.Column(accessor='occupation.region.name.upper')
         r3 = tables.Column(accessor='occupation.region.name', verbose_name='OVERRIDE')
+        trans_test = tables.Column()
+        trans_test_lazy = tables.Column()
 
     # The Person model has a ``first_name`` and ``last_name`` field, but only
     # the ``last_name`` field has an explicit ``verbose_name`` set. This means
@@ -122,6 +124,20 @@ def verbose_name():
     Assert('Name') == table.columns['r1'].verbose_name
     Assert('Name') == table.columns['r2'].verbose_name
     Assert('OVERRIDE') == table.columns['r3'].verbose_name
+    Assert("Translation Test") == table.columns["trans_test"].verbose_name
+    Assert("Translation Test Lazy") == table.columns["trans_test_lazy"].verbose_name
+
+    # -------------------------------------------------------------------------
+
+    # Now we'll try using a table with Meta.model
+    class PersonTable(tables.Table):
+        class Meta:
+            model = Person
+    # Issue #16
+    table = PersonTable([])
+    Assert("Translation Test") == table.columns["trans_test"].verbose_name
+    Assert("Translation Test Lazy") == table.columns["trans_test_lazy"].verbose_name
+
 
 @models.test
 def column_mapped_to_nonexistant_field():
index 700a482bf8998bc716d642c77802330e4ea39792..6e675fecc1c98dcbbe6a3c30cf24908627d32b79 100644 (file)
@@ -1,4 +1,6 @@
 from django.db import models
+from django.utils.translation import ugettext_lazy
+from django.utils.translation import ugettext
 
 
 class Person(models.Model):
@@ -6,6 +8,8 @@ class Person(models.Model):
     last_name = models.CharField(max_length=200, verbose_name='Surname')
     occupation = models.ForeignKey('Occupation', related_name='people',
                                    null=True, verbose_name='Occupation')
+    trans_test = models.CharField(max_length=200, blank=True, verbose_name=ugettext("Translation Test"))
+    trans_test_lazy = models.CharField(max_length=200, blank=True, verbose_name=ugettext("Translation Test Lazy"))
 
     def __unicode__(self):
         return self.first_name