fixed minor bug (caches not reset); added update() method
authorMichael Elsdörfer <michael@elsdoerfer.info>
Thu, 19 Jun 2008 18:52:07 +0000 (18:52 +0000)
committerMichael Elsdörfer <michael@elsdoerfer.info>
Thu, 19 Jun 2008 18:52:07 +0000 (18:52 +0000)
django_tables/models.py
django_tables/tables.py
tests/test_basic.py
tests/test_models.py

index b0587e3cee21ed0baea1024da8ef11f07b96cf88..26d742ec664d807d65d388cd1183994f48f10519 100644 (file)
@@ -96,6 +96,11 @@ class BaseModelTable(BaseTable):
         """Overridden. The snapshot in this case is simply a queryset\r
         with the necessary filters etc. attached.\r
         """\r
+\r
+        # reset caches\r
+        self._columns._reset()\r
+        self._rows = None\r
+\r
         queryset = self.queryset\r
         if self.order_by:\r
             queryset = queryset.order_by(*self._cols_to_fields(self.order_by))\r
index da6c504423016e2ecb719afdcf465b3ffa7cf9e1..5216207d1c77ca86cf74f2893a7498de524462b0 100644 (file)
@@ -136,6 +136,11 @@ class BaseTable(object):
         In the case of this base table implementation, a copy of the\r
         source data is created, and then modified appropriately.\r
         """\r
+\r
+        # reset caches\r
+        self._columns._reset()\r
+        self._rows = None\r
+\r
         snapshot = copy.copy(self._data)\r
         for row in snapshot:\r
             # delete unknown columns that are in the source data, but that\r
@@ -239,6 +244,17 @@ class BaseTable(object):
     def as_html(self):\r
         pass\r
 \r
+    def update(self):\r
+        """Update the table based on it's current options.\r
+\r
+        Normally, you won't have to call this method, since the table\r
+        updates itself (it's caches) automatically whenever you change\r
+        any of the properties. However, in some rare cases those\r
+        changes might not be picked up, for example if you manually\r
+        change ``base_columns`` or any of the columns in it.\r
+        """\r
+        self._build_snapshot()\r
+\r
 class Table(BaseTable):\r
     "A collection of columns, plus their associated data rows."\r
     # This is a separate class from BaseTable in order to abstract the way\r
@@ -262,6 +278,10 @@ class Columns(object):
         self.table = table\r
         self._columns = SortedDict()\r
 \r
+    def _reset(self):\r
+        """Used by parent table class."""\r
+        self._columns = SortedDict()\r
+\r
     def _spawn_columns(self):\r
         # (re)build the "_columns" cache of BoundColumn objects (note that\r
         # ``base_columns`` might have changed since last time); creating\r
index 086decc1d663df8bfcef7f2b51862d302e28f1f2..e2f8d16fc842fbe540613bc8624a70ba5cb21bca 100644 (file)
@@ -81,11 +81,6 @@ def test_basic():
     books.base_columns['test'] = tables.Column()\r
     assert not 'test' in BookTable.base_columns\r
 \r
-    # make sure the row and column caches work\r
-    assert id(list(books.columns)[0]) == id(list(books.columns)[0])\r
-    # TODO: row cache currently not used\r
-    #assert id(list(books.rows)[0]) == id(list(books.rows)[0])\r
-\r
     # optionally, exceptions can be raised when input is invalid\r
     tables.options.IGNORE_INVALID_OPTIONS = False\r
     raises(Exception, "books.order_by = '-name,made-up-column'")\r
@@ -95,6 +90,28 @@ def test_basic():
     # reset for future tests\r
     tables.options.IGNORE_INVALID_OPTIONS = True\r
 \r
+def test_caches():\r
+    """Ensure the various caches are effective.\r
+    """\r
+\r
+    class BookTable(tables.Table):\r
+        name = tables.Column()\r
+        answer = tables.Column(default=42)\r
+    books = BookTable([\r
+        {'name': 'Foo: Bar'},\r
+    ])\r
+\r
+    assert id(list(books.columns)[0]) == id(list(books.columns)[0])\r
+    # TODO: row cache currently not used\r
+    #assert id(list(books.rows)[0]) == id(list(books.rows)[0])\r
+\r
+    # test that caches are reset after an update()\r
+    old_column_cache = id(list(books.columns)[0])\r
+    old_row_cache = id(list(books.rows)[0])\r
+    books.update()\r
+    assert id(list(books.columns)[0]) != old_column_cache\r
+    assert id(list(books.rows)[0]) != old_row_cache\r
+\r
 def test_sort():\r
     class BookTable(tables.Table):\r
         id = tables.Column()\r
index 542d3008265df64044201362744e4b5ed92f4228..b2ca09c8d052342d4955b133093ddd288f2cf453 100644 (file)
@@ -125,11 +125,27 @@ def test_basic():
     countries = CountryTable(Country)\r
     test_country_table(countries)\r
 \r
-    # make sure the row and column caches work for model tables as well\r
+def test_caches():\r
+    """Make sure the caches work for model tables as well (parts are\r
+    reimplemented).\r
+    """\r
+    class CountryTable(tables.ModelTable):\r
+        class Meta:\r
+            model = Country\r
+            exclude = ('id',)\r
+    countries = CountryTable()\r
+\r
     assert id(list(countries.columns)[0]) == id(list(countries.columns)[0])\r
     # TODO: row cache currently not used\r
     #assert id(list(countries.rows)[0]) == id(list(countries.rows)[0])\r
 \r
+    # test that caches are reset after an update()\r
+    old_column_cache = id(list(countries.columns)[0])\r
+    old_row_cache = id(list(countries.rows)[0])\r
+    countries.update()\r
+    assert id(list(countries.columns)[0]) != old_column_cache\r
+    assert id(list(countries.rows)[0]) != old_row_cache\r
+\r
 def test_sort():\r
     class CountryTable(tables.ModelTable):\r
         tld = tables.Column(name="domain")\r
@@ -172,5 +188,4 @@ def test_pagination():
 \r
 # TODO: pagination\r
 # TODO: support function column sources both for modeltables (methods on model) and static tables (functions in dict)\r
-# TODO: manual base columns change -> update() call (add as example in docstr here) -> rebuild snapshot: is row cache, column cache etc. reset?\r
 # TODO: support relationship spanning columns (we could generate select_related() automatically)
\ No newline at end of file