o
    ˷ej                     @   s   d dl Z d dlmZ d dlmZ d dlmZ d dlmZ d dl	m
Z
 d dlmZ d dlmZ d	d
lmZ d	dlmZ d	dlmZ d	dlmZ d	dlmZmZmZmZmZ G dd deZG dd dZG dd dedZ e dddfddZ!dS )    N)OrderedDict)count)settings)	Paginator)models)get_template)	force_str   )columns)RequestConfig)	TableData)	BoundRows)AccessorAttributeDictOrderByOrderByTupleSequencec                       s    e Zd ZdZ fddZ  ZS )DeclarativeColumnsMetaclassz
    Metaclass that converts `.Column` objects defined on a class to the
    dictionary `.Table.base_columns`, taking into account parent class
    `base_columns` as well.
    c                    s   t |dd | |d< }g i }}| D ]\}}t|tjr+d|_|||f q|||< q|}|jdd d g }	t	|D ]}
t
|
drPt|
j |	 }	q@t|	}|jrt }|jd ur||jD ]}tjjt||j||j|d||< qcn|jjjD ]}tjj||j|j|jd	||j< q| D ]\}}||v r|| jdu rq|||< q|t| |jD ]}||v r|| q|D ]}||v r|| q| D ]}d }||jv rd}||jv rd
}|d ur||| _q||d< t | |||S )NMeta_metaTc                 S   s
   | d j S )Nr	   )creation_counter)x r   L/var/www/ideatree/venv/lib/python3.10/site-packages/django_tables2/tables.py<lambda>&   s   
 z5DeclarativeColumnsMetaclass.__new__.<locals>.<lambda>)keybase_columns)fieldaccessorlinkify)r   r   F)TableOptionsgetitems
isinstancer
   Column	_explicitappendsortreversedhasattrlistr   r   modelfieldslibrarycolumn_for_fieldr   	get_fieldr   r   nameupdateexcludepopkeyslocalize
unlocalizesuper__new__)mcsr0   basesattrsoptscols	remainder	attr_nameattrparent_columnsbaser   extra
field_namer   r   column	exclusioncol_namelocalize_column	__class__r   r   r8      sj   












z#DeclarativeColumnsMetaclass.__new__)__name__
__module____qualname____doc__r8   __classcell__r   r   rI   r   r      s    r   c                       s(   e Zd ZdZ fddZdd Z  ZS )r    a  
    Extracts and exposes options for a `.Table` from a `.Table.Meta`
    when the table is defined. See `.Table` for documentation on the impact of
    variables in this class.

    Arguments:
        options (`.Table.Meta`): options for a table from `.Table.Meta`
    c                    s  t    | || ttdd}ttdi }t|d|| _t|di | _t|di | _t|dd| _t|d	d | _	t|d
d | _
t|dg }t|tsRt|d}|| _t|dd| _t|dd }t|trj|f}|d urrt|nd | _t|dd| _t|dd| _t|dd| _t|dd| _t|dd| _t|dd| _t|dd| _t|dd| _t|dd| _t|dd | _t|d|| _t|dd| _t|d d| _d S )!NDJANGO_TABLES2_TEMPLATEzdjango_tables2/table.htmlDJANGO_TABLES2_TABLE_ATTRSr;   	row_attrspinned_row_attrsdefaultu   —
empty_textr,   r   Tr2   r   order_byorder_by_fieldr'   
page_fieldpageper_page   per_page_fieldprefix show_headershow_footersequence	orderabler+   template_namer5   r6   ) r7   __init___check_typesgetattrr   r;   rR   rS   rT   rU   r,   r#   dictfromkeysr   r2   strr   rV   rW   rX   rZ   r\   r]   r_   r`   ra   rb   r+   rc   r5   r6   )selfoptions
class_namerP   rQ   r   rV   rI   r   r   rd   u   sD   


zTableOptions.__init__c           	      C   s   |du rdS t fg dtfdgtttfg dttttfdgtg dtfg dtttfdgttj	fd	gi}|
 D ]5\}}|D ].}t||d}|durmt||smd
||| }td|t|jddd |D q?q9dS )zI
        Check class Meta attributes to prevent common mistakes.
        N)r_   r`   rb   rZ   )r,   ra   r2   r5   r6   r   )rc   r]   rW   rX   r\   )r;   rR   rS   rV   r+   z
{}.{} = {}z*{} (type {}), but type must be one of ({})z, c                 S   s   g | ]}|j qS r   )rK   ).0tr   r   r   
<listcomp>   s    z-TableOptions._check_types.<locals>.<listcomp>)boolinttupler*   setrg   ri   typer   Modelr"   rf   r#   format__repr__	TypeErrorrK   join)	rj   rk   rl   checkstypesr4   r   value
expressionr   r   r   re      s0   

zTableOptions._check_types)rK   rL   rM   rN   rd   re   rO   r   r   rI   r   r    k   s    	'r    c                       s  e Zd ZdZ																			d: fdd	Zdd Zdd	 Zd
d Zdd Zd;ddZ	dd Z
edd Zejdd Zedd Zejdd Zedd Zejdd Zedd Zejdd Zeddfdd Zed!d" Zejd#d" Zed$d% Zejd&d% Zed'd( Zed)d* Zed+d, Zed-d. Zejd/d. Zed0d1 Zejd2d1 Zed3d4 Zejd5d4 Zed6d7 Zd8d9 Z  ZS )<Tablea  
    A representation of a table.

    Arguments:
        data (QuerySet, list of dicts): The data to display.
            This is a required variable, a `TypeError` will be raised if it's not passed.

        order_by: (tuple or str): The default ordering tuple or comma separated str.
            A hyphen `-` can be used to prefix a column name to indicate
            *descending* order, for example: `("name", "-age")` or `name,-age`.

        orderable (bool): Enable/disable column ordering on this table

        empty_text (str): Empty text to render when the table has no data.
            (default `.Table.Meta.empty_text`)

        exclude (iterable or str): The names of columns that should not be
            included in the table.

        attrs (dict): HTML attributes to add to the ``<table>`` tag.
            When accessing the attribute, the value is always returned as an
            `.AttributeDict` to allow easily conversion to HTML.

        row_attrs (dict): Add custom html attributes to the table rows.
            Allows custom HTML attributes to be specified which will be added
            to the ``<tr>`` tag of the rendered table.

        pinned_row_attrs (dict): Same as row_attrs but for pinned rows.

        sequence (iterable): The sequence/order of columns the columns (from
            left to right).

            Items in the sequence must be :term:`column names <column name>`, or
            `"..."` (string containing three periods). `'...'` can be used as a
            catch-all for columns that are not specified.

        prefix (str): A prefix for query string fields.
            To avoid name-clashes when  using multiple tables on single page.

        order_by_field (str): If not `None`, defines the name of the *order by*
            query string field in the URL.

        page_field (str): If not `None`, defines the name of the *current page*
            query string field.

        per_page_field (str): If not `None`, defines the name of the *per page*
            query string field.

        template_name (str): The template to render when using ``{% render_table %}``
            (defaults to DJANGO_TABLES2_TEMPLATE, which is ``"django_tables2/table.html"``
            by default).

        default (str): Text to render in empty cells (determined by
            `.Column.empty_values`, default `.Table.Meta.default`)

        request: Django's request to avoid using `RequestConfig`

        show_header (bool): If `False`, the table will not have a header
            (`<thead>`), defaults to `True`

        show_footer (bool): If `False`, the table footer will not be rendered,
            even if some columns have a footer, defaults to `True`.

        extra_columns (str, `.Column`): list of `(name, column)`-tuples containing
            extra columns to add to the instance. If `column` is `None`, the column
            with `name` will be removed from the table.
    NTc                    sl  t    |d u rtdt| j|p| jj| _|	| _t	j
|d| _| j|  |d u r2| jj}|| _t|p;| jj| _|  |  d| _t| j| | jd| _t|d urY|n| jj| _dD ]}t| j|i | j|< qat|pv| jj| _|d ur|n| jj| _|| _|
| _|| _|| _|| _|| _|| _t !t| j" |d ur|D ]\}}|d u r| v r |= q| |< q|	d ur|	}	n| jjr| jj}	n| jj#d urt$| jj#d }	nd}	t%|	}	|	& ' | _(t) fdd|	D  t*+|  | _*|d u r| jj,d ur| jj,}|d u r d | _-| jj.}|d ur|| _,n|| _,|| _/|r0t0|1|  t2 | _3d S )	NzArgument data to {} is required)data)topbottom)r   tablepinned_data)theadtbodytfoot)z...c                 3   s$    | ]}| v r| | fV  qd S Nr   )rm   r   r   r   r   	<genexpr>]  s   " z!Table.__init__.<locals>.<genexpr>)4r7   rd   rx   rv   rt   rK   r   r2   ra   r   	from_datar   	set_tablerT   r   rS   get_top_pinned_dataget_bottom_pinned_datar   r   rowsr;   r!   rR   rU   rb   r]   rW   rX   r\   r_   r`   copydeepcopyr   r,   rr   r   expandr4   	_sequencer   r
   BoundColumnsrV   	_order_byorderingrc   r   	configurer   _counter)rj   r   rV   rb   rU   r2   r;   rR   rS   ra   r]   rW   rX   r\   rc   rT   requestr_   r`   extra_columnstagr0   rE   rI   r   r   rd      sr   




zTable.__init__c                 C      dS )a&  
        Return data for top pinned rows containing data for each row.
        Iterable type like: QuerySet, list of dicts, list of objects.
        Having a non-zero number of pinned rows
        will not result in an empty result set message being rendered,
        even if there are no regular data rows

        Returns:
            `None` (default) no pinned rows at the top, iterable, data for pinned rows at the top.

        Note:
            To show pinned row this method should be overridden.

        Example:
            >>> class TableWithTopPinnedRows(Table):
            ...     def get_top_pinned_data(self):
            ...         return [{
            ...             "column_a" : "some value",
            ...             "column_c" : "other value",
            ...         }]
        Nr   rj   r   r   r   r   u     zTable.get_top_pinned_datac                 C   r   )a5  
        Return data for bottom pinned rows containing data for each row.
        Iterable type like: QuerySet, list of dicts, list of objects.
        Having a non-zero number of pinned rows
        will not result in an empty result set message being rendered,
        even if there are no regular data rows

        Returns:
            `None` (default) no pinned rows at the bottom, iterable, data for pinned rows at the bottom.

        Note:
            To show pinned row this method should be overridden.

        Example:
            >>> class TableWithBottomPinnedRows(Table):
            ...     def get_bottom_pinned_data(self):
            ...         return [{
            ...             "column_a" : "some value",
            ...             "column_c" : "other value",
            ...         }]
        Nr   r   r   r   r   r     r   zTable.get_bottom_pinned_datac                 C   r   )a  
        A way to hook into the moment just before rendering the template.

        Can be used to hide a column.

        Arguments:
            request: contains the `WGSIRequest` instance, containing a `user` attribute if
                `.django.contrib.auth.middleware.AuthenticationMiddleware` is added to
                your `MIDDLEWARE_CLASSES`.

        Example::

            class Table(tables.Table):
                name = tables.Column(orderable=False)
                country = tables.Column(orderable=False)

                def before_render(self, request):
                    if request.user.has_perm('foo.delete_bar'):
                        self.columns.hide('country')
                    else:
                        self.columns.show('country')
        Nr   )rj   r   r   r   r   before_render  s   zTable.before_renderc                 C   s0   t  | _t| j}| |d}| | ||S )zU
        Render the table to an HTML table, adding `request` to the context.
        )r   r   )r   r   r   rc   r   render)rj   r   templatecontextr   r   r   as_html  s
   



zTable.as_htmlc                 #   sZ     du rd  fdd| j  D }dd |D V  | jD ]fdd|D V  qdS )a-  
        Return a row iterator of the data which would be shown in the table where
        the first row is the table headers.

        arguments:
            exclude_columns (iterable): columns to exclude in the data iterator.

        This can be used to output the table data as CSV, excel, for example using the
        `~.export.ExportMixin`.

        If a column is defined using a :ref:`table.render_FOO`, the returned value from
        that method is used. If you want to differentiate between the rendered cell
        and a value, use a `value_Foo`-method::

            class Table(tables.Table):
                name = tables.Column()

                def render_name(self, value):
                    return format_html('<span class="name">{}</span>', value)

                def value_name(self, value):
                    return value

        will have a value wrapped in `<span>` in the rendered HTML, and just returns
        the value when `as_values()` is called.

        Note that any invisible columns will be part of the row iterator.
        Nr   c                    s"   g | ]}|j js|j v s|qS r   )rE   exclude_from_exportr0   rm   rE   )exclude_columnsr   r   ro     s    
z#Table.as_values.<locals>.<listcomp>c                 S   s   g | ]	}t |jd dqS T)strings_only)r   headerr   r   r   r   ro     s    c                    s    g | ]}t  |jd dqS r   )r   get_cell_valuer0   r   )rowr   r   ro     s    )r
   iterallr   )rj   r   r
   r   )r   r   r   	as_values  s   



zTable.as_valuesc                 C   s   | j otdd | jD S )z{
        Returns True if any of the columns define a ``_footer`` attribute or a
        ``render_footer()`` method
        c                 s   s    | ]}|  V  qd S r   )
has_footerr   r   r   r   r     s    z#Table.has_footer.<locals>.<genexpr>)r`   anyr
   r   r   r   r   r     s   zTable.has_footerc                 C      | j d ur| j S | jjS r   )_show_headerr   r_   r   r   r   r   r_        zTable.show_headerc                 C   
   || _ d S r   )r   rj   r|   r   r   r   r_        
c                 C      | j S r   )r   r   r   r   r   rV        zTable.order_byc                 C   sx   |sdn|}t |tr|dn|}g }|D ]}t|j}|| jv r-| j| jr-|| qt|| _	| j
| j	 dS )z
        Order the rows of the table based on columns.

        Arguments:
            value: iterable or comma separated string of order by aliases.
        r   ,N)r#   ri   splitr   barer
   rb   r&   r   r   r   rV   )rj   r|   rV   validaliasr0   r   r   r   rV     s   	


c                 C   r   r   )_order_by_fieldr   rW   r   r   r   r   rW   !     zTable.order_by_fieldc                 C   r   r   )r   r   r   r   r   rW   '  r   c                 C   r   r   )_page_fieldr   rX   r   r   r   r   rX   +  r   zTable.page_fieldc                 C   r   r   )r   r   r   r   r   rX   /  r   r	   c                 O   s:   |p| j j}|| j|g|R i || _| j|| _| S )a  
        Paginates the table using a paginator and creates a ``page`` property
        containing information for the current page.

        Arguments:
            paginator_class (`~django.core.paginator.Paginator`): A paginator class to
                paginate the results.

            per_page (int): Number of records to display on each page.
            page (int): Page to display.

        Extra arguments are passed to the paginator.

        Pagination exceptions (`~django.core.paginator.EmptyPage` and
        `~django.core.paginator.PageNotAnInteger`) may be raised from this
        method and should be handled by the caller.
        )r   rZ   r   	paginatorrY   )rj   paginator_classrZ   rY   argskwargsr   r   r   paginate3  s   zTable.paginatec                 C   r   r   )_per_page_fieldr   r\   r   r   r   r   r\   L  r   zTable.per_page_fieldc                 C   r   r   )r   r   r   r   r   r\   R  r   c                 C   r   r   )_prefixr   r]   r   r   r   r   r]   V  r   zTable.prefixc                 C   r   r   )r   r   r   r   r   r]   Z  r   c                 C      d| j | jf S Nz%s%s)r]   rW   r   r   r   r   prefixed_order_by_field^     zTable.prefixed_order_by_fieldc                 C   r   r   )r]   rX   r   r   r   r   prefixed_page_fieldb  r   zTable.prefixed_page_fieldc                 C   r   r   )r]   r\   r   r   r   r   prefixed_per_page_fieldf  r   zTable.prefixed_per_page_fieldc                 C   r   r   )r   r   r   r   r   ra   j  r   zTable.sequencec                 C   s&   |rt |}|| j  || _d S r   )r   r   r   r4   r   r   r   r   r   ra   n  s   
c                 C   r   r   )
_orderabler   rb   r   r   r   r   rb   u     
zTable.orderablec                 C   r   r   )r   r   r   r   r   rb   |  r   c                 C   r   r   )	_templater   rc   r   r   r   r   rc     r   zTable.template_namec                 C   r   r   )r   r   r   r   r   rc     r   c                 C   s   t | dr	| jjS | jS )z`
        Return the rows for the current page if the table is paginated, else all rows.
        rY   )r)   rY   object_listr   r   r   r   r   paginated_rows  s   
zTable.paginated_rowsc                 C   s   |S )a  
        Returns a set of HTML class names for cells (both ``td`` and ``th``) of a
        **bound column** in this table.
        By default this returns the column class names defined in the table's
        attributes.
        This method can be overridden to change the default behavior, for
        example to simply `return classes_set`.

        Arguments:
            classes_set(set of string): a set of class names to be added
              to the cell, retrieved from the column's attributes. In the case
              of a header cell (th), this also includes ordering classes.
              To set the classes for a column, see `.Column`.
              To configure ordering classes, see :ref:`ordering-class-name`

            bound_column(`.BoundColumn`): the bound column the class names are
              determined for. Useful for accessing `bound_column.name`.

        Returns:
            A set of class names to be added to cells of this column

        If you want to add the column names to the list of classes for a column,
        override this method in your custom table::

            class MyTable(tables.Table):
                ...

                def get_column_class_names(self, classes_set, bound_column):
                    classes_set = super().get_column_class_names(classes_set, bound_column)
                    classes_set.add(bound_column.name)

                    return classes_set
        r   )rj   classes_setbound_columnr   r   r   get_column_class_names  s   "zTable.get_column_class_names)NNNNNNNNNNNNNNNNNTNr   )rK   rL   rM   rN   rd   r   r   r   r   r   r   propertyr_   setterrV   rW   rX   r   r   r\   r]   r   r   r   ra   rb   rc   r   r   rO   r   r   rI   r   r~      s    Fu
-





















r~   )	metaclassc           
      C   s   d| i}|dur||d< |dur||d< |dur||d< t |dr&|jtfntf}td||}| jd }d|i}	t|||f|	S )a  
    Return Table class for given `model`, equivalent to defining a custom table class::

        class MyTable(tables.Table):
            class Meta:
                model = model

    Arguments:
        model (`~django.db.models.Model`): Model associated with the new table
        table (`.Table`): Base Table class used to create the new one
        fields (list of str): Fields displayed in tables
        exclude (list of str): Fields exclude in tables
        localize (list of str): Fields to localize
    r+   Nr,   r2   r5   r   AutogeneratedTable)r)   r   objectrt   rK   )
r+   r   r,   r2   r5   r;   parentr   rl   table_class_attrsr   r   r   table_factory  s   
r   )"r   collectionsr   	itertoolsr   django.confr   django.core.paginatorr   	django.dbr   django.template.loaderr   django.utils.encodingr   r^   r
   configr   r   r   r   r   utilsr   r   r   r   r   rt   r   r    r~   r   r   r   r   r   <module>   s*    YP    