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): selection = tables.CheckBoxColumn( accessor="pk", orderable=False, attrs={ 'th': {'class': 'selection-col'}, 'td': {'class': 'selection-col'}, 'input': {'name': 'selection'}, }, verbose_name='' ) class Meta: attrs = {"class": "table js-row-selectable", "data-selection-name": "selection"} def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) try: cols = list(self.columns.names()) if 'selection' in cols: cols.remove('selection') cols.append('selection') try: self.reorder_columns(cols) except Exception: self.sequence = tuple(cols) except Exception: pass 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: pass self.caption = self.row_selection_controls @property def row_selection_controls(self): token = (self.attrs or {}).get('data-selection-token', format(id(self), 'x')) html = ( f"
" f"
" f" " f"
" f" " f" " f"
" f"
" f"
" f" Selected: 0" f"
" f"
" ) script = """ """ # Replace the simple placeholder with the runtime token. Using # a plain triple-quoted string avoids f-string brace parsing errors # from the JavaScript code which contains many `{`/`}` characters. script = script.replace('__TOKEN__', token) return mark_safe(html + script) class SingleImageColumn(tables.Column): def render(self, value): try: thumbnailer = get_thumbnailer(value) return format_html('', thumbnailer["exam-list"]) except InvalidImageFormatError: return format_html('Invalid image url', value) class BlockImageColumn(tables.Column): def render(self, value): blocks = [] for obj in value.all(): blocks.append(obj.get_block()) return mark_safe( """ {} """.format("".join(blocks)) ) class SeriesImageColumn(tables.Column): def render(self, value): #obj = value.first() images = value.all() if not images: return mark_safe('None
') obj = findMiddle(images) if obj is None: return "None" image_object = obj.image try: thumbnailer = get_thumbnailer(image_object) return format_html( '
[{}]', thumbnailer["exam-list"], value.count(), ) except InvalidImageFormatError: return format_html( 'Invalid image url
[{}]', image_object, value.count(), ) class FirstImageColumn(tables.Column): def render(self, value): obj = value.all() if not obj: return mark_safe('No image') image_object = obj[0].image try: thumbnailer = get_thumbnailer(image_object) return format_html('', thumbnailer["exam-list"]) except InvalidImageFormatError: return format_html('Invalid image url', image_object) class CidUserTable(SelectionTable): cid = tables.LinkColumn( "cid_scores", args=[A("cid"), A("passcode")], orderable=True ) # physics_exams = tables.ManyToManyColumn(verbose_name="Physics Exams") # rapid_exams = tables.ManyToManyColumn(verbose_name="Rapid Exams") # sba_exams = tables.ManyToManyColumn(verbose_name="SBA Exams") # longs_exams = tables.ManyToManyColumn(verbose_name="Long Exams") # anatomy_exams = tables.ManyToManyColumn(verbose_name="Anatomy Exams") group = tables.Column(linkify=True) #selection = tables.CheckBoxColumn(accessor="pk", orderable=False) emails = tables.Column(empty_values=(), orderable=False) edit = tables.LinkColumn( "generic:update_cid", text="Edit", args=[A("pk")], orderable=True ) class Meta(SelectionTable.Meta): model = CidUser template_name = "django_tables2/bootstrap4.html" fields = ( # "cid", "passcode", "active", "group", "internal_candidate", # "email", ) sequence = ("cid", "passcode", "active", "internal_candidate", "emails") def __init__(self, data=None, *args, **kwargs): super().__init__( data.prefetch_related("group"), *args, **kwargs, ) def render_emails(self, value, record): print(self) if record.supervisor is not None: return format_html("""{}\n[{}]""", record.email, record.supervisor.email) else: return record.email class CidUserExamTable(SelectionTable): cid = tables.LinkColumn( "cid_scores", args=[A("cid"), A("passcode")], orderable=True ) physics_exams = tables.ManyToManyColumn(verbose_name="Physics Exams") rapid_exams = tables.ManyToManyColumn(verbose_name="Rapid Exams") sba_exams = tables.ManyToManyColumn(verbose_name="SBA Exams") longs_exams = tables.ManyToManyColumn(verbose_name="Long Exams") anatomy_exams = tables.ManyToManyColumn(verbose_name="Anatomy Exams") #selection = tables.CheckBoxColumn(accessor="pk", orderable=False) emails = tables.Column(empty_values=(), orderable=False) edit = tables.LinkColumn( "generic:update_cid", text="Edit", args=[A("pk")], orderable=True ) class Meta(SelectionTable.Meta): model = CidUser template_name = "django_tables2/bootstrap4.html" fields = ( # "cid", "passcode", "active", "group", "internal_candidate", # "email", ) sequence = ("cid", "passcode", "active", "internal_candidate", "emails") def __init__(self, data=None, *args, **kwargs): super().__init__( data.prefetch_related( "physics_exams", "rapid_exams", "sba_exams", "anatomy_exams", "longs_exams", "group", ), *args, **kwargs, ) def render_emails(self, value, record): if record.supervisor is not None: return format_html("""{}\n[{}]""", record.email, record.supervisor.email) else: return record.email # def render_cid(self, value, record): # return format_html("""Popup""", record.pk) class UserUserTable(SelectionTable): user = tables.Column( linkify={"viewname": "account_profile", "args": [A("username")]}, orderable=True, verbose_name="User", empty_values=(), ) supervisor = tables.Column( linkify={ "viewname": "generic:supervisor_detail", "args": [A("userprofile__supervisor__pk")], }, orderable=True, verbose_name="Supervisor", accessor=A("userprofile__supervisor"), ) #selection = tables.CheckBoxColumn(accessor="pk", orderable=False) edit = tables.Column( empty_values=(), linkify={"viewname": "account_update", "args": [A("username")]}, orderable=False, verbose_name="Edit", ) admin_edit = tables.Column( empty_values=(), linkify={"viewname": "admin:auth_user_change", "args": [A("pk")]}, orderable=False, verbose_name="Admin", ) user_groups = tables.ManyToManyColumn(verbose_name="Groups", linkify_item=True) date_joined = tables.DateTimeColumn(format="Y/m/d") class Meta(SelectionTable.Meta): model = User template_name = "django_tables2/bootstrap4.html" fields = ( # "cid", # "userprofile", "userprofile__grade", "date_joined", # "user_groups", # "userprofile.supervisor", # "email", ) sequence = ( "user", "userprofile__grade", "supervisor", "user_groups", "date_joined", "edit", "admin_edit", ) def __init__(self, data=None, *args, **kwargs): super().__init__( data.prefetch_related( "userprofile", "user_groups", "userprofile__grade", "supervisor", ), *args, **kwargs, ) # This should be avoidable? def render_edit(self, value, record): return "Edit" def render_admin_edit(self, value, record): return "Admin" def render_user(self, value, record): span_class = "" if record.userprofile.peninsula_trainee: span_class = "peninsula-trainee" return format_html( "
{} {}
{}
{}
", span_class, record.first_name, record.last_name, record.username, record.email, ) class ExaminationTable(SelectionTable): examination = tables.Column( linkify=("generic:examination_detail", {"pk": tables.A("pk")}), verbose_name="Condition", ) #edit = tables.LinkColumn( # "generic:examination_update", text="Edit", args=[A("pk")], orderable=False #) delete = tables.LinkColumn( "generic:examination_delete", text="Delete", args=[A("pk")], orderable=False ) #selection = tables.CheckBoxColumn(accessor="pk", orderable=False) # synonym = tables.ManyToManyColumn(verbose_name="Synonyms") #synonym = tables.Column(empty_values=()) #parent = tables.ManyToManyColumn(verbose_name="Parents") class Meta(SelectionTable.Meta): model = Examination template_name = "django_tables2/bootstrap4.html" #fields = ("primary", "subspecialty") sequence = ("examination",) class SupervisorTable(SelectionTable): name = tables.Column( linkify=("generic:supervisor_detail", {"pk": tables.A("pk")}), verbose_name="Name", ) # We don't use a link column as we want to add a redirect parameter edit = tables.Column( accessor="pk", orderable=False ) class Meta(SelectionTable.Meta): model = Supervisor template_name = "django_tables2/bootstrap4.html" sequence = ("name", "email") exclude = ("id",) SelectionTable.Meta.attrs.update({"id": "supervisor-table"}) def render_edit(self, value, record): url = f"{reverse("generic:supervisor_edit", args=[record.pk])}?redirect={self.request.path}" return format_html("Edit", url)