from django.urls import reverse
import django_tables2 as tables
from django_tables2.utils import A
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from easy_thumbnails.files import get_thumbnailer
from easy_thumbnails.exceptions import InvalidImageFormatError
from generic.models import CidUser, Examination, Supervisor, findMiddle
from django.contrib.auth.models import User
# Generic selection-enabled table base class.
# Inherit from this class to automatically get a selection checkbox
# column (input name="selection") and table attrs that client-side
# scripts can use to find selectable tables.
class SelectionTable(tables.Table):
# Provide a default selection checkbox column. Subclasses that wish to
# customise can override this attribute.
selection = tables.CheckBoxColumn(
accessor="pk",
orderable=False,
attrs={
'th': {'class': 'selection-col'},
'td': {'class': 'selection-col'},
'input': {'name': 'selection'},
},
verbose_name=''
)
class Meta:
# Defaults: add js-row-selectable class so client-side code can
# locate tables that support row selection.
attrs = {"class": "table js-row-selectable", "data-selection-name": "selection"}
def __init__(self, *args, **kwargs):
# Ensure selection column is always placed last in the column order
# so that table actions/controls appear to the right. We attempt to
# reorder columns after initialization; if django-tables2 provides
# `reorder_columns`, use it, otherwise fall back to setting
# `self.sequence`.
super().__init__(*args, **kwargs)
try:
cols = list(self.columns.names())
if 'selection' in cols:
cols.remove('selection')
cols.append('selection')
try:
# Preferred API when available
self.reorder_columns(cols)
except Exception:
# Fallback: set sequence attribute
self.sequence = tuple(cols)
except Exception:
# Defensive: don't break table rendering if introspection fails
pass
# Expose a per-instance selection token and ensure the table has the
# `js-row-selectable` class so client-side scripts (or the inline
# initializer below) can find the correct table without extra markup
# in templates.
try:
token = format(id(self), 'x')
attrs = getattr(self, 'attrs', None) or {}
classes = attrs.get('class', '')
if 'js-row-selectable' not in classes:
attrs['class'] = (classes + ' js-row-selectable').strip()
attrs['data-selection-token'] = token
self.attrs = attrs
except Exception:
# non-fatal
pass
# By default render the row selection controls above the table so
# templates don't need to include `{{ table.row_selection_controls }}`.
try:
# `row_selection_controls` is already marked safe HTML.
self.caption = self.row_selection_controls
except Exception:
pass
@property
def row_selection_controls(self):
"""Return HTML for the row-selection control bar.
Usage: render in template with `{{ table.row_selection_controls|safe }}`
The control IDs are suffixed with a small per-instance token to
avoid collisions when multiple tables are present on the same page.
"""
token = (self.attrs or {}).get('data-selection-token', format(id(self), 'x'))
html = (
"