class FooTable(Table): a = Column.number( ) # This is a shortcut that results in the css class "rj" (for right justified) being added to the header and cell b = Column() c = Column(cell__format=lambda table, column, row, value: value[-1] ) # Display the last value of the tuple sum_c = Column(cell__value=lambda table, column, row: sum(row.c), sortable=False) # Calculate a value not present in Foo
class TestTable(Table): class Meta: endpoint__data = lambda table, key, value: [{ cell.bound_column.name: cell.value for cell in row } for row in table] foo = Column() bar = Column()
class TestTable(NoSortTable): class Meta: attrs__class__classy = True attrs__foo = lambda table: 'bar' row__attrs__class__classier = True row__attrs__foo = lambda table: "barier" yada = Column()
class TestTable(Table): class Meta: attrs = { 'class': lambda table: 'listview', 'id': lambda table: 'table_id', } foo = Column() bar = Column.number()
class TestTable(NoSortTable): class Meta: attrs = {'class': 'classy', 'foo': lambda table: 'bar'} row__attrs = { 'class': 'classier', 'foo': lambda table, row: "barier" } yada = Column()
class TestTable(Table): foo__a = Column.number() foo__b = Column() foo = Column.choice_queryset( model=Foo, choices=lambda table, column: Foo.objects.all(), query__show=True, bulk__show=True, query__gui__show=True)
class BarTable(Table): select = Column.select( ) # Shortcut for creating checkboxes to select rows b__a = Column.number( # Show "a" from "b". This works for plain old objects too. query__show=True, # put this field into the query language query__gui__show=True ) # put this field into the simple filtering GUI c = Column( bulk__show=True, # Enable bulk editing for this field query__show=True, query__gui__show=True)
class TestTable(Table): class Meta: attrs = { 'class': 'listview', 'id': 'table_id', } foo = Column() bar = Column.number() icon = Column.icon('history', is_report, group="group") edit = Column.edit(is_report, group="group") delete = Column.delete(is_report)
def explicit_table(): columns = [ Column(name="foo"), Column.number(name="bar"), ] return Table(data=get_data(), columns=columns, attrs=lambda table: { 'class': 'listview', 'id': 'table_id' })
def test_query_namespace_inject(): class FooException(Exception): pass def post_validation(form): del form raise FooException() with pytest.raises(FooException): foo = Table(data=[], model=Foo, request=Struct(method='POST', POST={'-': '-'}, GET=Struct(urlencode=lambda: None)), columns=[ Column(name='foo', query__show=True, query__gui__show=True) ], query__gui__post_validation=post_validation) foo.prepare(foo.request)
class BarTable(Table): select = Column.select( ) # Shortcut for creating checkboxes to select rows b__a = Column.number( ) # Show "a" from "b". This works for plain old objects too. b = Column.choice_queryset( show=False, choices=Foo.objects.all(), model=Foo, bulk__show=True, query__show=True, query__gui__show=True, ) c = Column(bulk=True) # The form is created automatically d = Column( display_name='Display name', css_class={'css_class'}, url='url', title='title', sortable=False, group='Foo', auto_rowspan=True, cell__value=lambda table, column, row: row.b.a // 3, cell__format=lambda table, column, row, value: '- %s -' % value, cell__attrs__class__cj=True, cell__attrs__title='cell title', cell__url='url', cell__url_title='cell url title') e = Column(group='Foo', cell__value='explicit value', sortable=False) f = Column(show=False, sortable=False) g = Column(attr='c', sortable=False) django_templates_for_cells = Column( sortable=False, cell__value=None, cell__template='kitchen_sink_cell_template.html') class Meta: model = Bar
class TestTable(NoSortTable): foo = Column(auto_rowspan=True)
class TestTable(NoSortTable): foo = Column(display_name="Bar")
class MyTable(Table): foo = Column(after='bar') bar = Column()
class TestTable(NoSortTable): sentinel1 = 'sentinel1' sentinel2 = Column(cell__value=lambda table, column, row: '%s %s %s' % (table.sentinel1, column.name, row.sentinel3))
class TestTable(NoSortTable): foo = Column() bar = Column.icon('foo', show=show_callable)
class TestTable(NoSortTable): foo = Column() bar = Column() class Meta: row__template = lambda table: 'test_table_row.html'
class Meta: columns = [Column(name='foo')]
class TestTable(Table): foo__bar = Column(sortable=False)
class TestTable(Table): a = Column.number( sortable=False, bulk__show=True ) # turn off sorting to not get the link with random query params b = Column(bulk__show=True)
class MyTable(Table): class Meta: columns = [Column(name='foo')] bar = Column()
class TestTable(NoSortTable): foo = Column(url="/some/url")
class TestTable(Table): a = Column.number( sortable=False ) # turn off sorting to not get the link with random query params b = Column( show=False) # should still be able to filter on this though!
class TestTable(NoSortTable): foo = Column() bar = Column(show=False)
def render_room(request, room_pk, **kwargs): # TODO: @dispatch on this view, and params to be able to customize rendering of the room room = get_object_or_404(Room, pk=room_pk) user_time = get_user_time(user=request.user, identifier=f'forum/room:{room.pk}') show_hidden = bool_parse(request.GET.get('show_hidden', '0')) def unread_from_here_href(row: Message, **_): params = request.GET.copy() params.setlist('unread_from_here', [row.last_changed_time.isoformat()]) return mark_safe('?' + params.urlencode() + "&") if 'time' in request.GET: unread2_time = datetime.fromisoformat(request.GET['time']) else: unread2_time = datetime.now() # NOTE: there's a set_user_time at the very bottom of this function if 'unread_from_here' in request.GET: user_time = datetime.fromisoformat(request.GET['unread_from_here']) # TODO: show many pages at once if unread? Right now we show the first unread page. start_page = None if 'page' not in request.GET: # Find first unread page try: first_unread_message = Message.objects.filter( room=room, last_changed_time__gte=user_time).order_by('path')[0] messages_before_first_unread = room.message_set.filter( path__lt=first_unread_message.path).count() start_page = messages_before_first_unread // PAGE_SIZE except IndexError: pass messages = Message.objects.filter(room__pk=room_pk).prefetch_related( 'user', 'room') if not show_hidden: messages = messages.filter(visible=True) def is_unread(row, **_): return row.last_changed_time >= user_time def is_unread2(row, **_): return row.last_changed_time >= unread2_time and not is_unread(row=row) def preprocess_data(data, table, **_): data = list(data) first_new = None for d in data: if is_unread(row=d): first_new = d break table.extra.unread = first_new is not None first_new_or_last_message = first_new if first_new_or_last_message is None and data: first_new_or_last_message = data[-1] if first_new_or_last_message is not None: # This is used by the view first_new_or_last_message.first_new = True return data result = render_table( request, template=get_template('forum/room.html'), paginator=RoomPaginator(messages), context=dict( obj=room, # required for header.html room=room, show_hidden=show_hidden, time=unread2_time or user_time, is_subscribed=is_subscribed(user=request.user, identifier=f'forum/room:{room.pk}'), is_mobile=request.user_agent.is_mobile, **kwargs, ), table__data=messages, table__exclude=['path'], table__extra_fields=[ Column(name='unread_from_here_href', attr=None, cell__value=unread_from_here_href), ], table__preprocess_data=preprocess_data, table__header__template=Template(''), table__row__template=get_template('forum/message.html'), table__row__attrs=dict( class__indent_0=lambda row, **_: row.indent == 0, class__message=True, class__current_user=lambda row, **_: request.user == row.user, class__other_user=lambda row, **_: request.user != row.user, class__unread=is_unread, class__unread2=is_unread2, ), table__attrs__cellpadding='0', table__attrs__cellspacing='0', table__attrs__id='first_newtable', table__attrs__align='center', table__attrs__class__roomtable=True, table__paginator__template='forum/blank.html', page=start_page, ) if 'unread_from_here' not in request.GET: user_time = datetime.now() set_user_time(user=request.user, identifier=f'forum/room:{room.pk}', time=user_time) return result
class TestTable(NoSortTable): foo = Column(cell__template='test_cell_template.html', cell__format=explode, cell__url=explode, cell__url_title=explode)
class TestTable(NoSortTable): foo = Column(attrs__class__some_class=True) legacy_foo = Column(css_class={"some_other_class"}) legacy_bar = Column(cell__attrs={'class': 'foo'}, cell__attrs__class__bar=True)
class TestTable(NoSortTable): class Meta: header__template = None foo = Column()
class TestTable(NoSortTable): foo = Column(title="Some title")
class TestTable(NoSortTable): foo = Column() bar = Column(attr='foo')