Source code for django_tables2.views

# coding: utf-8
from __future__ import unicode_literals

from itertools import count

from django.core.exceptions import ImproperlyConfigured
from django.views.generic.list import ListView

from .config import RequestConfig


class TableMixinBase(object):
    '''
    Base mixin for table-related class based views.
    '''

    context_table_name = 'table'
    table_pagination = None

    def get_table_class(self):
        '''
        Return the class to use for the table.
        '''
        if self.table_class:
            return self.table_class
        klass = type(self).__name__
        raise ImproperlyConfigured(
            'A table class was not specified. Define {}.table_class'.format(klass)
        )

    def get_context_table_name(self, table):
        '''
        Get the name to use for the table's template variable.
        '''
        return self.context_table_name

    def get_table_pagination(self, table):
        '''
        Returns pagination options: True for standard pagination (default),
        False for no pagination, and a dictionary for custom pagination.
        '''
        paginate = self.table_pagination

        if hasattr(self, 'paginate_by') and self.paginate_by is not None:
            # Since ListView knows the concept paginate_by, we use that if no
            # other pagination is configured.
            paginate = paginate or {}
            paginate['per_page'] = self.paginate_by

        if paginate is None:
            return True

        return paginate


[docs]class SingleTableMixin(TableMixinBase): ''' Adds a Table object to the context. Typically used with `.TemplateResponseMixin`. Attributes: table_class: subclass of `.Table` table_data: data used to populate the table, any compatible data source. context_table_name(str): name of the table's template variable (default: 'table') table_pagination (dict): controls table pagination. If a `dict`, passed as the *paginate* keyword argument to `.RequestConfig`. As such, any Truthy value enables pagination. (default: enable pagination) This mixin plays nice with the Django's`.MultipleObjectMixin` by using `.get_queryset`` as a fallback for the table data source. ''' table_class = None table_data = None
[docs] def get_table(self, **kwargs): ''' Return a table object to use. The table has automatic support for sorting and pagination. ''' table_class = self.get_table_class() table = table_class(self.get_table_data(), **kwargs) RequestConfig(self.request, paginate=self.get_table_pagination(table)).configure(table) return table
[docs] def get_table_data(self): ''' Return the table data that should be used to populate the rows. ''' if self.table_data is not None: return self.table_data elif hasattr(self, 'object_list'): return self.object_list elif hasattr(self, 'get_queryset'): return self.get_queryset() klass = type(self).__name__ raise ImproperlyConfigured( 'Table data was not specified. Define {}.table_data'.format(klass) )
[docs] def get_table_kwargs(self): ''' Return the keyword arguments for instantiating the table. ''' return {}
[docs] def get_context_data(self, **kwargs): ''' Overriden version of `.TemplateResponseMixin` to inject the table into the template's context. ''' context = super(SingleTableMixin, self).get_context_data(**kwargs) table = self.get_table(**self.get_table_kwargs()) context[self.get_context_table_name(table)] = table return context
class SingleTableView(SingleTableMixin, ListView): ''' Generic view that renders a template and passes in a `.Table` instances. '''
[docs]class MultiTableMixin(TableMixinBase): ''' Adds a Table object to the context. Typically used with `.TemplateResponseMixin`. the `tables` attribute must be either a list of `.Table` instances or classes extended from `.Table` which are not already instantiated. In that case, tables_data must be defined, having an entry containing the data for each table in `tables`. Attributes: tables: list of `.Table` instances or list of `.Table` child objects. tables_data: if defined, `tables` is assumed to be a list of table classes which will be instatiated with the corresponding item from this list of `.TableData` instances. table_prefix(str): Prefix to be used for each table. The string must contain one instance of `{}`, which will be replaced by an integer different for each table in the view. Default is 'table_{}-'. context_table_name(str): name of the table's template variable (default: 'tables') .. versionadded:: 1.2.3 ''' tables = None tables_data = None table_prefix = 'table_{}-' # override context table name to make sense in a multiple table context context_table_name = 'tables' def get_tables(self): if not self.tables: klass = type(self).__name__ raise ImproperlyConfigured( 'No tables were specified. Define {}.tables'.format(klass) ) return self.tables def get_context_data(self, **kwargs): context = super(MultiTableMixin, self).get_context_data(**kwargs) if self.tables_data is None: tables = self.get_tables() else: data = self.tables_data if len(data) != len(self.get_tables()): klass = type(self).__name__ raise ImproperlyConfigured( 'len({}.tables_data) != len({}.tables)'.format(klass, klass) ) tables = list(Table(data[i]) for i, Table in enumerate(self.tables)) # apply prefixes and execute requestConfig for each table table_counter = count() for table in tables: table.prefix = self.table_prefix.format(next(table_counter)) RequestConfig(self.request, paginate=self.get_table_pagination(table)).configure(table) context[self.get_context_table_name(table)] = list(tables) return context