1616import numpy as np
1717from plotly import offline
1818from plotly import graph_objs as go
19+ from django .utils .module_loading import import_string
1920
2021from tom_observations .utils import get_sidereal_visibility
2122from tom_targets .base_models import BaseTarget
@@ -381,7 +382,7 @@ def target_table_headers(model: type[BaseTarget]) -> list[str]:
381382 headers .append ("Saved Data" )
382383 else :
383384 try :
384- field = model ._meta .get_field (column ) # type: ignore[attr-defined])
385+ field = model ._meta .get_field (column )
385386 headers .append (field .verbose_name )
386387 except FieldDoesNotExist :
387388 headers .append (column )
@@ -401,7 +402,7 @@ def target_table_row(target: BaseTarget) -> list[Any]:
401402 row .append (target .dataproduct_set .count ())
402403 else :
403404 try :
404- field = target ._meta .get_field (column ) # type: ignore[attr-defined])
405+ field = target ._meta .get_field (column )
405406 value = getattr (target , column )
406407 if field .get_internal_type () in ["FloatField" , "DecimalField" ]:
407408 try :
@@ -504,3 +505,53 @@ def extra_form_field(form, field):
504505 if field not in [e ['name' ] for e in settings .EXTRA_FIELDS ]:
505506 raise AttributeError ("Attempted to lookup non-defined extra field" )
506507 return form [field ]
508+
509+
510+ def get_app_tabs (context ):
511+ """
512+ Imports the target detail tab content from relevant apps into the template.
513+
514+ Each target_tab should be contained in a list of dictionaries in an app's apps.py `target_detail_tabs` method.
515+ Each target_tab dictionary should contain a 'context' key with the path to the context processor class
516+ (typically a templatetag), a 'partial' key with the path to the html partial template, and a 'label' key with
517+ a string describing the label for the tab.
518+
519+ FOR EXAMPLE:
520+ [{'partial': 'path/to/partial.html',
521+ 'context': 'path/to/context/data/method',
522+ 'label: 'Nice String'}]
523+ """
524+ target_tabs_to_display = []
525+ for app in apps .get_app_configs ():
526+ try :
527+ target_tabs = app .target_detail_tabs ()
528+ except AttributeError :
529+ continue
530+ if target_tabs :
531+ for tab in target_tabs :
532+ new_context = {}
533+ if tab .get ('context' ):
534+ try :
535+ context_method = import_string (tab .get ('context' ))
536+ except ImportError as e :
537+ logger .warning (f'WARNING: Could not import context for { app .name } target detail tab from '
538+ f'{ tab ["context" ]} .\n '
539+ f'{ e } ' )
540+ continue
541+ new_context = context_method (context )
542+ target_tabs_to_display .append ({'partial' : tab ['partial' ],
543+ 'context' : new_context ,
544+ 'label' : tab ['label' ]})
545+ return target_tabs_to_display
546+
547+
548+ @register .inclusion_tag ('tom_targets/partials/app_tab_divs.html' , takes_context = True )
549+ def include_app_tab_divs (context ):
550+ context ['target_tabs_to_display' ] = get_app_tabs (context )
551+ return context
552+
553+
554+ @register .inclusion_tag ('tom_targets/partials/app_tabs.html' , takes_context = True )
555+ def include_app_tabs (context ):
556+ context ['target_tabs_to_display' ] = get_app_tabs (context )
557+ return context
0 commit comments