【问题标题】:How to add counter column in django-tables2?如何在 django-tables2 中添加计数器列?
【发布时间】:2020-11-24 00:20:23
【问题描述】:

我正在尝试使用 django-tables2 在表格的第一列上添加一个计数器,但下面的解决方案仅在 # 列下显示全 0。我应该如何添加一个列,该列将有一列对行进行编号?

tables.py:

import django_tables2 as tables
from profiles.models import Track
import itertools
counter = itertools.count()

class PlaylistTable(tables.Table):

    priority = tables.Column(verbose_name="#", default=next(counter))

    class Meta:
        model = Track
        attrs = {"class": "paleblue"}
        orderable = False
        fields = ('priority', 'artist', 'title')

我的模板:

{% render_table table %}

【问题讨论】:

  • 您可以尝试将默认值设置为 lambda _: next(counter),尽管这样会很丑陋/hacky。

标签: python django django-tables2


【解决方案1】:

其他答案都在tables.py 文件的顶级范围内具有itertools.count 实例。这使得计数器在页面加载之间保持不变,只有在服务器重新启动时才会重置。更好的解决方案是将计数器作为实例变量添加到表上,如下所示:

import django_tables2 as tables
import itertools

class CountryTable(tables.Table):
    counter = tables.Column(empty_values=(), orderable=False)

    def render_counter(self):
        self.row_counter = getattr(self, 'row_counter', itertools.count())
        return next(self.row_counter)

这将确保每次实例化表时都会重置计数器。

【讨论】:

    【解决方案2】:

    来自Column的文档

    default (str or callable):

    列的默认值。这可以是一个值或可调用对象[1]。如果数据中的对象为列提供None,则将使用默认值。

    [1] - The provided callable object must not expect to receive any arguments.

    你传递的 next(counter) 你传递的函数的结果似乎是一个整数。

    你可以定义一个函数:

    def next_count():
        return next(counter)
    

    并且,将其用作默认值:

    priority = tables.Column(verbose_name="#", default=next_count)
    

    或者,您可以使用@Sayse 的 cmets 中提到的 lambda 函数:

    priority = tables.Column(verbose_name="#", default=lambda: next(counter))
    

    【讨论】:

    • 虽然对 lambda 感到厌烦,但 django 会尝试阻止您将模型默认设置为 lambda(有点阻止这种事情)。我也不确定这对异步请求的支持程度。
    • 在这种情况下,使用该函数的第一种方法会很有用。 :)
    • 是的,作为可调用对象会更好,但问题仍然是计数器是全局的,即使您要制作两次表格,计数器也会从最后一个完成的位置开始又是 1 个 :)
    • 是的..这是真的。我不确定 OP 想要达到什么目的。
    • Sayse 是对的。刷新页面会导致计数器从最后一行完成的位置开始。我只是想添加一个计数器列来显示每一行的位置,以便于行参考。
    【解决方案3】:

    基于 Jieter 的回答,您可以通过这个小修改来处理分页:

    import django_tables2 as tables
    import itertools
    
    class CountryTable(tables.Table):
        counter = tables.Column(empty_values=(), orderable=False)
    
        def render_counter(self):
            self.row_counter = getattr(self, 'row_counter',
                                       itertools.count(self.page.start_index()))
            return next(self.row_counter)
    

    即使在第一页之后的页面中,行编号也将是全局正确的。请注意,在这种情况下,索引是从 1 开始的。

    【讨论】:

      【解决方案4】:

      添加到杰特的回答中, 在您的表类中,实现这些功能。 init 方法用于从视图类获取请求变量以获取页码。 将 render_id 更改为 render_yourcolumn 名称。

      class ClassName:
          def __init__(self, *args, **kwargs):
              self.request = kwargs.pop('request', None)
              super(ClassName, self).__init__(*args, **kwargs)
      
          def render_id(self):
              page = int(self.request.GET.get('page', 1)) - 1
              self.row_counter = getattr(self, 'row_counter', itertools.count(start=page*25+1)) # Change 25 to the number of rows in one page
              return next(self.row_counter)
      

      现在在视图文件中,将您的 Table 类称为:

      table = ClassName(ModelName.objects.values(), request=request)
      

      通过这种方法,您的计数器对于 n 个页面将是正确的。 :)

      【讨论】:

        【解决方案5】:

        有类似的问题,没有找到任何简单的解决方案,可以在分页表上工作,而无需在每个页面上重置计数器

        来自官方FAQ:How to create a row counter?(不支持分页)

        使用已有的分页器属性: https://stackoverflow.com/a/9939938/3734484(类似一般django的做法)

        import django_tables2 as tables
        
        class NumberedTable(tables.Table):
            serial_column = tables.TemplateColumn(
                verbose_name='#',
                "{{ row_counter|add:table.page.start_index }}",
        
            )
           ...
        

        【讨论】:

          【解决方案6】:

          这是一种不专业的方法,不使用 itertools 模块:

          import django_tables2 as table
          
          class GenericTable(table.Table):
              """GenericTable
          
              """
              counter = table.Column(
                  verbose_name='#',
                  orderable=False,
                  accessor='pk',
              )
          
              def render_counter(self, record):
                  """render_counter
          
                  :param record: record
                  :return: custom render
                  """
                  records = list(self.data)
                  index = records.index(record)
          
                  # counter = index  # counter starts from 0
                  counter = index + 1  # counter starts from 1
                  return counter
          

          【讨论】:

            【解决方案7】:

            来自Jieter的回答

            如果不想从零开始每一页,你可以这样做:

            import django_tables2 as tables
            import itertools
            
            class CountryTable(tables.Table):
                counter = tables.Column(empty_values=(), orderable=False)
            
                def render_counter(self):
                    self.row_counter = getattr(self, 'row_counter', itertools.count())
                    return next(self.row_counter)+self.page.start_index()
                    # self.page.sart_index() is default Table function and return number of start index per page
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-08-24
              • 1970-01-01
              • 1970-01-01
              • 2013-11-19
              相关资源
              最近更新 更多