From 9f65ce1138c94f52900aedd173b85e873de16145 Mon Sep 17 00:00:00 2001 From: Joey Chatelain Date: Wed, 22 Oct 2025 15:46:15 -0700 Subject: [PATCH 1/2] add integration point --- .../auth/partials/app_user_lists.html | 2 +- tom_common/templatetags/tom_common_extras.py | 11 +++ tom_common/templatetags/user_extras.py | 15 +--- .../tom_targets/partials/app_tab_divs.html | 6 ++ .../tom_targets/partials/app_tabs.html | 6 ++ .../templates/tom_targets/target_detail.html | 2 + .../templates/tom_targets/target_list.html | 2 +- tom_targets/templatetags/targets_extras.py | 85 ++++++++++++++++++- 8 files changed, 112 insertions(+), 17 deletions(-) create mode 100644 tom_targets/templates/tom_targets/partials/app_tab_divs.html create mode 100644 tom_targets/templates/tom_targets/partials/app_tabs.html diff --git a/tom_common/templates/auth/partials/app_user_lists.html b/tom_common/templates/auth/partials/app_user_lists.html index 73d986661..3757cddbb 100644 --- a/tom_common/templates/auth/partials/app_user_lists.html +++ b/tom_common/templates/auth/partials/app_user_lists.html @@ -1,4 +1,4 @@ -{% load user_extras %} +{% load user_extras tom_common_extras %} {% for user_list in user_lists_to_display %} {% show_individual_app_partial user_list %}
diff --git a/tom_common/templatetags/tom_common_extras.py b/tom_common/templatetags/tom_common_extras.py index 3baba975d..cd574552f 100644 --- a/tom_common/templatetags/tom_common_extras.py +++ b/tom_common/templatetags/tom_common_extras.py @@ -171,3 +171,14 @@ def copy_button(text_to_copy='', help_text='Copy'): """ return {'copy_text': str(text_to_copy), 'copy_help': str(help_text)} + + +@register.inclusion_tag('tom_common/partials/include_app_partial.html', takes_context=True) +def show_individual_app_partial(context, app_partial_data): + """ + An Inclusion tag for setting the unique context for an app's partial. + """ + for item in app_partial_data['context']: + context[item] = app_partial_data['context'][item] + context['app_partial'] = app_partial_data['partial'] + return context diff --git a/tom_common/templatetags/user_extras.py b/tom_common/templatetags/user_extras.py index 56c7a494e..e5d35a1ea 100644 --- a/tom_common/templatetags/user_extras.py +++ b/tom_common/templatetags/user_extras.py @@ -54,10 +54,10 @@ def include_app_user_lists(context): for app_users in user_lists: try: context_method = import_string(app_users['context']) - except ImportError: + except ImportError as e: logger.warning(f'WARNING: Could not import context for {app.name} user list from ' f'{app_users["context"]}.\n' - f'Are you sure you have the right path?') + f'{e}') continue new_context = context_method(context) user_lists_to_display.append({'partial': app_users['partial'], 'context': new_context}) @@ -117,14 +117,3 @@ def show_app_profiles(context, user): context['user'] = user context['profiles_to_display'] = profiles_to_display return context - - -@register.inclusion_tag('tom_common/partials/include_app_partial.html', takes_context=True) -def show_individual_app_partial(context, app_partial_data): - """ - An Inclusion tag for setting the unique context for an app's partial. - """ - for item in app_partial_data['context']: - context[item] = app_partial_data['context'][item] - context['app_partial'] = app_partial_data['partial'] - return context diff --git a/tom_targets/templates/tom_targets/partials/app_tab_divs.html b/tom_targets/templates/tom_targets/partials/app_tab_divs.html new file mode 100644 index 000000000..1e8a56302 --- /dev/null +++ b/tom_targets/templates/tom_targets/partials/app_tab_divs.html @@ -0,0 +1,6 @@ +{% load targets_extras tom_common_extras%} +{% for target_tab in target_tabs_to_display %} +
+ {% show_individual_app_partial target_tab %} +
+{% endfor %} \ No newline at end of file diff --git a/tom_targets/templates/tom_targets/partials/app_tabs.html b/tom_targets/templates/tom_targets/partials/app_tabs.html new file mode 100644 index 000000000..442e57497 --- /dev/null +++ b/tom_targets/templates/tom_targets/partials/app_tabs.html @@ -0,0 +1,6 @@ +{% load targets_extras %} +{% for target_tab in target_tabs_to_display %} + +{% endfor %} \ No newline at end of file diff --git a/tom_targets/templates/tom_targets/target_detail.html b/tom_targets/templates/tom_targets/target_detail.html index 9bd27bb97..9c3ca35c6 100644 --- a/tom_targets/templates/tom_targets/target_detail.html +++ b/tom_targets/templates/tom_targets/target_detail.html @@ -71,6 +71,7 @@ + {% include_app_tabs %}
@@ -114,6 +115,7 @@

Observations

{% spectroscopy_for_target target %}
+ {% include_app_tab_divs %} {% comments_enabled as comments_are_enabled %} {% if comments_are_enabled %} diff --git a/tom_targets/templates/tom_targets/target_list.html b/tom_targets/templates/tom_targets/target_list.html index 41ae85ba2..c0d24c649 100644 --- a/tom_targets/templates/tom_targets/target_list.html +++ b/tom_targets/templates/tom_targets/target_list.html @@ -7,7 +7,7 @@
- {{ target_count }} Targets   + {{ target_count }} Target{{ target_count|pluralize }}   diff --git a/tom_targets/templatetags/targets_extras.py b/tom_targets/templatetags/targets_extras.py index 820069042..abd5dc78f 100644 --- a/tom_targets/templatetags/targets_extras.py +++ b/tom_targets/templatetags/targets_extras.py @@ -16,6 +16,7 @@ import numpy as np from plotly import offline from plotly import graph_objs as go +from django.utils.module_loading import import_string from tom_observations.utils import get_sidereal_visibility from tom_targets.base_models import BaseTarget @@ -383,7 +384,7 @@ def target_table_headers(model: type[BaseTarget]) -> list[str]: headers.append("Saved Data") else: try: - field = model._meta.get_field(column) # type: ignore[attr-defined]) + field = model._meta.get_field(column) headers.append(field.verbose_name) except FieldDoesNotExist: headers.append(column) @@ -403,7 +404,7 @@ def target_table_row(target: BaseTarget) -> list[Any]: row.append(target.dataproduct_set.count()) else: try: - field = target._meta.get_field(column) # type: ignore[attr-defined]) + field = target._meta.get_field(column) value = getattr(target, column) if field.get_internal_type() in ["FloatField", "DecimalField"]: try: @@ -506,3 +507,83 @@ def extra_form_field(form, field): if field not in [e['name'] for e in settings.EXTRA_FIELDS]: raise AttributeError("Attempted to lookup non-defined extra field") return form[field] + + +@register.inclusion_tag('tom_targets/partials/app_tab_divs.html', takes_context=True) +def include_app_tab_divs(context): + """ + Imports the user list content from relevant apps into the template. + + Each user_list should be contained in a list of dictionaries in an app's apps.py `user_lists` method. + Each user_list dictionary should contain a 'context' key with the path to the context processor class (typically a + templatetag), and a 'partial' key with the path to the html partial template. + + FOR EXAMPLE: + [{'partial': 'path/to/partial.html', + 'context': 'path/to/context/data/method'}] + """ + target_tabs_to_display = [] + for app in apps.get_app_configs(): + try: + target_tabs = app.target_detail_tabs() + except AttributeError: + continue + if target_tabs: + for tab in target_tabs: + new_context = {} + if tab.get('context'): + try: + context_method = import_string(tab['context']) + except ImportError as e: + logger.warning(f'WARNING: Could not import context for {app.name} target detail tab from ' + f'{tab["context"]}.\n' + f'{e}') + continue + new_context = context_method(context) + target_tabs_to_display.append({'partial': tab['partial'], + 'context': new_context, + 'label': tab['label']}) + + context['target_tabs_to_display'] = target_tabs_to_display + return context + + +@register.inclusion_tag('tom_targets/partials/app_tabs.html', takes_context=True) +def include_app_tabs(context): + """ + Imports the target detail tab content from relevant apps into the template. + + Each target_tab should be contained in a list of dictionaries in an app's apps.py `target_detail_tabs` method. + Each target_tab dictionary should contain a 'context' key with the path to the context processor class (typically a + templatetag), a 'partial' key with the path to the html partial template, and a 'label' key with a string + describing the label for the tab. + + FOR EXAMPLE: + [{'partial': 'path/to/partial.html', + 'context': 'path/to/context/data/method', + 'label: 'Nice String'}] + """ + target_tabs_to_display = [] + for app in apps.get_app_configs(): + try: + target_tabs = app.target_detail_tabs() + except AttributeError: + continue + if target_tabs: + for tab in target_tabs: + new_context = {} + if tab.get('context'): + try: + context_method = import_string(tab.get('context')) + except ImportError as e: + logger.warning(f'WARNING: Could not import context for {app.name} target detail tab from ' + f'{tab["context"]}.\n' + f'{e}') + continue + new_context = context_method(context) + target_tabs_to_display.append({'partial': tab['partial'], + 'context': new_context, + 'label': tab['label']}) + + context['target_tabs_to_display'] = target_tabs_to_display + return context From da44758fd4c915a0f92e4d71950eebae3e17c0de Mon Sep 17 00:00:00 2001 From: Joey Chatelain Date: Wed, 22 Oct 2025 16:16:30 -0700 Subject: [PATCH 2/2] consolodate app import code --- tom_targets/templatetags/targets_extras.py | 60 ++++++---------------- 1 file changed, 15 insertions(+), 45 deletions(-) diff --git a/tom_targets/templatetags/targets_extras.py b/tom_targets/templatetags/targets_extras.py index abd5dc78f..efa86cb17 100644 --- a/tom_targets/templatetags/targets_extras.py +++ b/tom_targets/templatetags/targets_extras.py @@ -509,54 +509,14 @@ def extra_form_field(form, field): return form[field] -@register.inclusion_tag('tom_targets/partials/app_tab_divs.html', takes_context=True) -def include_app_tab_divs(context): - """ - Imports the user list content from relevant apps into the template. - - Each user_list should be contained in a list of dictionaries in an app's apps.py `user_lists` method. - Each user_list dictionary should contain a 'context' key with the path to the context processor class (typically a - templatetag), and a 'partial' key with the path to the html partial template. - - FOR EXAMPLE: - [{'partial': 'path/to/partial.html', - 'context': 'path/to/context/data/method'}] - """ - target_tabs_to_display = [] - for app in apps.get_app_configs(): - try: - target_tabs = app.target_detail_tabs() - except AttributeError: - continue - if target_tabs: - for tab in target_tabs: - new_context = {} - if tab.get('context'): - try: - context_method = import_string(tab['context']) - except ImportError as e: - logger.warning(f'WARNING: Could not import context for {app.name} target detail tab from ' - f'{tab["context"]}.\n' - f'{e}') - continue - new_context = context_method(context) - target_tabs_to_display.append({'partial': tab['partial'], - 'context': new_context, - 'label': tab['label']}) - - context['target_tabs_to_display'] = target_tabs_to_display - return context - - -@register.inclusion_tag('tom_targets/partials/app_tabs.html', takes_context=True) -def include_app_tabs(context): +def get_app_tabs(context): """ Imports the target detail tab content from relevant apps into the template. Each target_tab should be contained in a list of dictionaries in an app's apps.py `target_detail_tabs` method. - Each target_tab dictionary should contain a 'context' key with the path to the context processor class (typically a - templatetag), a 'partial' key with the path to the html partial template, and a 'label' key with a string - describing the label for the tab. + Each target_tab dictionary should contain a 'context' key with the path to the context processor class + (typically a templatetag), a 'partial' key with the path to the html partial template, and a 'label' key with + a string describing the label for the tab. FOR EXAMPLE: [{'partial': 'path/to/partial.html', @@ -584,6 +544,16 @@ def include_app_tabs(context): target_tabs_to_display.append({'partial': tab['partial'], 'context': new_context, 'label': tab['label']}) + return target_tabs_to_display + + +@register.inclusion_tag('tom_targets/partials/app_tab_divs.html', takes_context=True) +def include_app_tab_divs(context): + context['target_tabs_to_display'] = get_app_tabs(context) + return context + - context['target_tabs_to_display'] = target_tabs_to_display +@register.inclusion_tag('tom_targets/partials/app_tabs.html', takes_context=True) +def include_app_tabs(context): + context['target_tabs_to_display'] = get_app_tabs(context) return context