using py.test for testing; added some tests; minor model bugfixes;
authorMichael Elsdörfer <michael@elsdoerfer.info>
Sat, 14 Jun 2008 17:34:59 +0000 (17:34 +0000)
committerMichael Elsdörfer <michael@elsdoerfer.info>
Sat, 14 Jun 2008 17:34:59 +0000 (17:34 +0000)
README
django_tables/columns.py
django_tables/models.py
tests/__init__.py [new file with mode: 0644]
tests/test_basic.py [moved from tests/test.py with 67% similarity]
tests/test_models.py [new file with mode: 0644]
tests/test_templates.py [new file with mode: 0644]

diff --git a/README b/README
index 940885756d59746d4253b94492240d60bc8185ef..704019a4cd4d69963b8d881a0441e7ba99b2ade1 100644 (file)
--- a/README
+++ b/README
@@ -1,3 +1,18 @@
+django-tables\r
+=============\r
+\r
+Installation\r
+------------\r
+\r
+Adding django-tables to your INSTALLED_APPS settings is optional, it'll get\r
+you the ability to load some template utilities via {% load tables %}, but\r
+apart from that, ``import django_tables as tables`` should get you going.\r
+\r
+Running the test suite\r
+----------------------\r
+\r
+The test suite uses py.test (from http://codespeak.net/py/dist/test.html).\r
+\r
 Tables and Pagination\r
 ---------------------\r
 \r
index 164bcd583276aa3ed62ad637290f2c91650e139d..1ee5e84b3dd795778d3131cba4cea59d033e7c69 100644 (file)
@@ -1,5 +1,5 @@
 __all__ = (\r
-    'Column',\r
+    'Column', 'TextColumn', 'NumberColumn',\r
 )\r
 \r
 class Column(object):\r
@@ -32,7 +32,7 @@ class Column(object):
         self.default = default\r
         self.visible = visible\r
         self.sortable = sortable\r
-        \r
+\r
         self.creation_counter = Column.creation_counter\r
         Column.creation_counter += 1\r
 \r
index bc820d24df54e5880f3928fc5c87373027feafd1..c0f8d1b6748e60db29e02245abb2451413109437 100644 (file)
@@ -1,4 +1,5 @@
-from tables import BaseTable, DeclarativeColumnsMetaclass\r
+from django.utils.datastructures import SortedDict\r
+from tables import BaseTable, DeclarativeColumnsMetaclass, Column\r
 \r
 __all__ = ('BaseModelTable', 'ModelTable')\r
 \r
@@ -23,7 +24,7 @@ def columns_for_model(model, columns=None, exclude=None):
     field_list = []\r
     opts = model._meta\r
     for f in opts.fields + opts.many_to_many:\r
-        if (fields and not f.name in fields) or \\r
+        if (columns and not f.name in columns) or \\r
            (exclude and f.name in exclude):\r
             continue\r
         column = Column()\r
@@ -45,7 +46,7 @@ class ModelTableMetaclass(DeclarativeColumnsMetaclass):
         # if a model is defined, then build a list of default columns and\r
         # let the declared columns override them.\r
         if opts.model:\r
-            columns = columns_for_model(opts.model, opts.fields, opts.exclude)\r
+            columns = columns_for_model(opts.model, opts.columns, opts.exclude)\r
             columns.update(self.declared_columns)\r
             self.base_columns = columns\r
         return self\r
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644 (file)
index 0000000..9ec883c
--- /dev/null
@@ -0,0 +1,3 @@
+# make django-tables available for import for tests\r
+import os, sys\r
+sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
\ No newline at end of file
similarity index 67%
rename from tests/test.py
rename to tests/test_basic.py
index 29ee0dbf7f77ac187a42d00cee8d0c79b5d20b67..3fe7fe6124f9214be4200991ee10e54f31f42bac 100644 (file)
@@ -1,6 +1,7 @@
-from django.core.paginator import Paginator\r
-import os, sys\r
-sys.path.append(os.path.join(os.path.dirname(__file__), '..'))\r
+"""Test the base table functionality.\r
+\r
+This includes the core, as well as static data, non-model tables.\r
+"""\r
 \r
 import django_tables as tables\r
 \r
@@ -43,7 +44,6 @@ def test_declaration():
     assert 'motto' in StateTable1.base_columns\r
     assert 'motto' in StateTable2.base_columns\r
 \r
-    # test more with actual models\r
 \r
 def test_basic():\r
     class BookTable(tables.Table):\r
@@ -93,59 +93,4 @@ def test_sort():
     books.columns['language'].sortable = False\r
     books.order_by = 'language'\r
     assert not books.order_by\r
-    test_order(('language', 'pages'), [1,3,2,4])  # as if: 'pages'\r
-\r
-def test_for_templates():\r
-    class BookTable(tables.Table):\r
-        id = tables.Column()\r
-        name = tables.Column()\r
-    books = BookTable([\r
-        {'id': 1, 'name': 'Foo: Bar'},\r
-    ])\r
-\r
-    # cast to a string we get a value ready to be passed to the querystring\r
-    books.order_by = ('name',)\r
-    assert str(books.order_by) == 'name'\r
-    books.order_by = ('name', '-id')\r
-    assert str(books.order_by) == 'name,-id'\r
-\r
-test_declaration()\r
-test_basic()\r
-test_sort()\r
-test_for_templates()\r
-\r
-\r
-"""\r
-<table>\r
-<tr>\r
-    {% for column in book.columns %}\r
-        <th><a href="{{ column.name }}">{{ column }}</a></th\r
-        <th><a href="{% set_url_param "sort" column.name }}">{{ column }}</a></th\r
-    {% endfor %}\r
-</tr>\r
-{% for row in book %}\r
-    <tr>\r
-        {% for value in row %}\r
-            <td>{{ value }]</td>\r
-        {% endfor %}\r
-    </tr>\r
-{% endfor %}\r
-</table>\r
-\r
-OR:\r
-\r
-<table>\r
-{% for row in book %}\r
-    <tr>\r
-        {% if book.columns.name.visible %}\r
-            <td>{{ row.name }]</td>\r
-        {% endif %}\r
-        {% if book.columns.score.visible %}\r
-            <td>{{ row.score }]</td>\r
-        {% endif %}\r
-    </tr>\r
-{% endfor %}\r
-</table>\r
-\r
-\r
-"""
\ No newline at end of file
+    test_order(('language', 'pages'), [1,3,2,4])  # as if: 'pages'
\ No newline at end of file
diff --git a/tests/test_models.py b/tests/test_models.py
new file mode 100644 (file)
index 0000000..48191e7
--- /dev/null
@@ -0,0 +1,72 @@
+"""Test ModelTable specific functionality.\r
+\r
+Sets up a temporary Django project using a memory SQLite database.\r
+"""\r
+\r
+from django.conf import settings\r
+\r
+def setup_module(module):\r
+    settings.configure(**{\r
+        'DATABASE_ENGINE': 'sqlite3',\r
+        'DATABASE_NAME': ':memory:',\r
+    })\r
+\r
+    from django.db import models\r
+\r
+    class City(models.Model):\r
+        name = models.TextField()\r
+        population = models.IntegerField()\r
+    module.City = City\r
+\r
+    class Country(models.Model):\r
+        name = models.TextField()\r
+        population = models.IntegerField()\r
+        capital = models.ForeignKey(City)\r
+        tld = models.TextField(verbose_name='Domain Extension', max_length=2)\r
+    module.Country = Country\r
+\r
+\r
+def test_nothing():\r
+    pass\r
+\r
+import django_tables as tables\r
+\r
+def test_declaration():\r
+    """Test declaration, declared columns and default model field columns.\r
+    """\r
+\r
+    class CountryTable(tables.ModelTable):\r
+        class Meta:\r
+            model = Country\r
+\r
+    assert len(CountryTable.base_columns) == 5\r
+    assert 'name' in CountryTable.base_columns\r
+    assert not hasattr(CountryTable, 'name')\r
+\r
+    # Override one model column, add another custom one, exclude one\r
+    class CountryTable(tables.ModelTable):\r
+        capital = tables.TextColumn(verbose_name='Name of capital')\r
+        projected = tables.Column(verbose_name="Projected Population")\r
+        class Meta:\r
+            model = Country\r
+            exclude = ['tld']\r
+\r
+    assert len(CountryTable.base_columns) == 5\r
+    assert 'projected' in CountryTable.base_columns\r
+    assert 'capital' in CountryTable.base_columns\r
+    assert not 'tld' in CountryTable.base_columns\r
+\r
+    # Inheritance (with a different model) + field restrictions\r
+    class CityTable(CountryTable):\r
+        class Meta:\r
+            model = City\r
+            columns = ['id', 'name']\r
+            exclude = ['capital']\r
+\r
+    print CityTable.base_columns\r
+    assert len(CityTable.base_columns) == 4\r
+    assert 'id' in CityTable.base_columns\r
+    assert 'name' in CityTable.base_columns\r
+    assert 'projected' in CityTable.base_columns # declared in parent\r
+    assert not 'population' in CityTable.base_columns  # not in Meta:columns\r
+    assert 'capital' in CityTable.base_columns  # in exclude, but only works on model fields (is that the right behaviour?)
\ No newline at end of file
diff --git a/tests/test_templates.py b/tests/test_templates.py
new file mode 100644 (file)
index 0000000..7d2e5bc
--- /dev/null
@@ -0,0 +1,56 @@
+"""Test template specific functionality.\r
+\r
+Make sure tables expose their functionality to templates right.\r
+"""\r
+\r
+import django_tables as tables\r
+\r
+def test_for_templates():\r
+    class BookTable(tables.Table):\r
+        id = tables.Column()\r
+        name = tables.Column()\r
+    books = BookTable([\r
+        {'id': 1, 'name': 'Foo: Bar'},\r
+    ])\r
+\r
+    # cast to a string we get a value ready to be passed to the querystring\r
+    books.order_by = ('name',)\r
+    assert str(books.order_by) == 'name'\r
+    books.order_by = ('name', '-id')\r
+    assert str(books.order_by) == 'name,-id'\r
+\r
+\r
+"""\r
+<table>\r
+<tr>\r
+    {% for column in book.columns %}\r
+        <th><a href="{{ column.name }}">{{ column }}</a></th\r
+        <th><a href="{% set_url_param "sort" column.name }}">{{ column }}</a></th\r
+    {% endfor %}\r
+</tr>\r
+{% for row in book %}\r
+    <tr>\r
+        {% for value in row %}\r
+            <td>{{ value }]</td>\r
+        {% endfor %}\r
+    </tr>\r
+{% endfor %}\r
+</table>\r
+\r
+OR:\r
+\r
+<table>\r
+{% for row in book %}\r
+    <tr>\r
+        {% if book.columns.name.visible %}\r
+            <td>{{ row.name }]</td>\r
+        {% endif %}\r
+        {% if book.columns.score.visible %}\r
+            <td>{{ row.score }]</td>\r
+        {% endif %}\r
+    </tr>\r
+{% endfor %}\r
+</table>\r
+\r
+\r
+"""
\ No newline at end of file