1 # -*- coding: utf-8 -*-
3 class BoundRow(object):
4 """Represents a *specific* row in a table.
6 :class:`BoundRow` objects expose rendered versions of raw table data. This
7 means that formatting (via :attr:`Column.formatter` or an overridden
8 :meth:`Column.render` method) is applied to the values from the table's
11 To access the rendered value of each cell in a row, just iterate over it:
13 .. code-block:: python
15 >>> import django_tables as tables
16 >>> class SimpleTable(tables.Table):
17 ... a = tables.Column()
18 ... b = tables.CheckBoxColumn(attrs={'name': 'my_chkbox'})
20 >>> table = SimpleTable([{'a': 1, 'b': 2}])
21 >>> row = table.rows[0] # we only have one row, so let's use it
26 <input type="checkbox" name="my_chkbox" value="2" />
28 Alternatively you can treat it like a list and use indexing to retrieve a
29 specific cell. It should be noted that this will raise an IndexError on
32 .. code-block:: python
37 u'<input type="checkbox" name="my_chkbox" value="2" />'
40 IndexError: list index out of range
42 Finally you can also treat it like a dictionary and use column names as the
43 keys. This will raise KeyError on failure (unlike the above indexing using
46 .. code-block:: python
51 u'<input type="checkbox" name="my_chkbox" value="2" />'
57 def __init__(self, table, data):
58 """Initialise a new :class:`BoundRow` object where:
60 * *table* is the :class:`Table` in which this row exists.
61 * *data* is a chunk of data that describes the information for this
62 row. A "chunk" of data might be a :class:`Model` object, a ``dict``,
63 or perhaps something else.
70 """Iterate over the rendered values for cells in the row.
72 Under the hood this method just makes a call to :meth:`__getitem__` for
76 for value in self.values:
79 def __getitem__(self, name):
80 """Returns the final rendered value for a cell in the row, given the
83 bound_column = self.table.columns[name]
84 # use custom render_FOO methods on the table
85 custom = getattr(self.table, 'render_%s' % name, None)
87 return custom(bound_column, self)
88 return bound_column.column.render(self.table, bound_column, self)
90 def __contains__(self, item):
91 """Check by both row object and column name."""
92 if isinstance(item, basestring):
93 return item in self.table._columns
99 for column in self.table.columns:
100 # this uses __getitem__, using the name (rather than the accessor)
101 # is correct – it's what __getitem__ expects.
102 yield self[column.name]
106 """Container for spawning BoundRows.
108 This is bound to a table and provides it's ``rows`` property. It
109 provides functionality that would not be possible with a simple
110 iterator in the table class.
112 def __init__(self, table):
113 """Initialise a :class:`Rows` object. *table* is the :class:`Table`
114 object in which the rows exist.
120 """Return an iterable for all :class:`BoundRow` objects in the table.
123 for row in self.table.data:
124 yield BoundRow(self.table, row)
127 """If the table is paginated, return an iterable of :class:`BoundRow`
128 objects that appear on the current page, otherwise return None.
131 if not hasattr(self.table, 'page'):
133 return iter(self.table.page.object_list)
136 """Convience method for all()"""
140 """Returns the number of rows in the table."""
141 return len(self.table.data)
143 # for compatibility with QuerySetPaginator
146 def __getitem__(self, key):
147 """Allows normal list slicing syntax to be used."""
148 if isinstance(key, slice):
150 for row in self.table.data[key]:
151 result.append(BoundRow(self.table, row))
153 elif isinstance(key, int):
154 return BoundRow(self.table, self.table.data[key])
156 raise TypeError('Key must be a slice or integer.')