django-tables2 css для сгруппированных строк - PullRequest
0 голосов
/ 06 сентября 2018

Использование django-tables2 было большим удовольствием. Я сейчас пытаюсь выяснить, как изменить CSS для строк, на основе содержимого строки. Например, с учетом таблицы:

header 1 | header 2
---------|---------
value 1  | 1
value 2  | 1
value 3  | 2
value 4  | 2
value 5  | 2
value 6  | 3
value 7  | 3

Я бы хотел иметь возможность стилизовать последовательные строки с одинаковыми значениями 'header 2' с одним и тем же классом. С itertools.groupby достаточно легко сгруппировать значения, которые должны быть сгруппированы, но я не могу понять, как перемещаться по объекту таблицы и обновлять атрибуты класса для каждой строки.

Для столбцов можно динамически обновлять атрибуты. Например, в init работает self.columns ['ColumnName']. Column.attrs = {'td': {'class': 'foo'}}. Однако для строк это (и различные перестановки) не работает:

for i in self.rows:
    i.attrs = {'tr': {'class': 'foo'}}  # *** AttributeError, can't set attribute
    i.cells.row.attrs = {...}           # *** AttributeError
    i.cells.row.attrs['class'] = 'foo'  # Seems to work, but attrs not updated
    # same as above
    i.cells.row.attrs.update({'tr': {'class': 'foo'}})
    i.table.row_attrs = {'class': 'foo'} # works, but applies to the whole table at once.

Очевидно, у меня здесь не тот конец палки. Документация предлагает использовать row_attrs в классе Meta, и в нем может быть функция для возврата значения класса. Тем не менее, в этой функции можно видеть только одну строку за раз (передаваемую как объект «запись»), тогда как в этом случае необходимо проанализировать таблицу целиком, поэтому init выглядит как лучшее место для решения этой проблемы.

Решение этой сложной ситуации или любые указатели были бы очень благодарны.

1 Ответ

0 голосов
/ 13 сентября 2018

Если вы хотите получить доступ к предыдущим строкам, вы можете использовать вызываемую функцию, возвращающую вызываемую строку следующим образом:

def group_by_heading():
    class_names = ["red", "blue", "yellow", ...]
    previous = None

    def inner(record):
        # in first row and after every change, remove the first element
        # and use it as the current class name.
        if previous is None or record.header_2 != previous.header_2:
            class_name = class_names.pop(0)

        previous = record
        return class_name
    return inner


class Table(tables.Table):
    class Meta:
        row_attrs = {'td': {'class': group_by_heading()}}

Обратите внимание, что функция group_by_heading называется и называется при добавлении ее к диктовке row_attrs. Это называется закрытие

Обратите внимание, что это не полный пример. Если применить имя как есть, список class_names будет быстро exhausted, потому что он используется повторно каждый раз, когда таблица отображается. Вы можете исправить это, добавив row_attrs к таблице в вашем представлении. Например, используя SingleTableView:

class MyView(tables.SingleTableView):
    table_class = MyTable
    queryset = Model.objects.all()

    def get_table_kwargs(self):
        return {"row_attrs": {'td': {'class': group_by_heading()}}}

Это обеспечит использование нового списка имен классов в каждом табличном представлении.

...