Skip to content

Commit

Permalink
Merge branch 'feature/swift-facility' of https://github.com/TOMToolki…
Browse files Browse the repository at this point in the history
…t/tom_base into feature/swift-facility
  • Loading branch information
phycodurus committed May 12, 2023
2 parents c8da460 + b12f888 commit a14fb52
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 7 deletions.
3 changes: 3 additions & 0 deletions docs/targets/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ TOM Toolkit. The ``Target`` defines the concept of an astronomical target.
:doc:`Adding Custom Target Fields <target_fields>` - Learn how to add custom fields to your TOM Targets if the
defaults do not suffice.

:doc:`Adding Custom Target Matcher <target_matcher>` - Learn how to replace or modify the TargetMatchManager if more
options are needed.

:doc:`Target API <../api/tom_targets/models>` - Take a look at the available properties for a ``Target`` and its associated models.

:doc:`Target Views <../api/tom_targets/views>` - Familiarize yourself with the available Target Views.
Expand Down
57 changes: 57 additions & 0 deletions docs/targets/target_matcher.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
Adding Custom Target Matcher
----------------------------

The role of the ``TargetMatchManager`` is to return a queryset of targets that match a given set of parameters.
By default, the TOM Toolkit includes a ``TargetMatchManager`` that contains a ``check_for_fuzzy_match`` function that
will return a queryset of ``TargetNames`` that are "similar" to a given string. This function will check for
case-insensitive aliases while ignoring spaces, dashes, underscore, and parentheses. This function is used during
``validate_unique`` when the target is saved to ensure that redundant targets are not added.

Under certain circumstances a user may wish to modify or add to this behavior.

Using the TargetMatchManager
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The ``TargetMatchManager`` is a django model manager defined as ``Target.matches``.
Django model managers are described in more detail in the `Django Docs <https://docs.djangoproject.com/en/4.2/topics/db/managers/>`_.

Overriding the TargetMatchManager
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

To start, find the ``MATCH_MANAGERS`` definition in your ``settings.py``:

.. code:: python
# Define MATCH_MANAGERS here. This is a dictionary that contains a dotted module path to the desired match manager
# for a given model.
# For example:
# MATCH_MANAGERS = {
# "Target": "my_custom_code.match_managers.MyCustomTargetMatchManager"
# }
MATCH_MANAGERS = {}
Add the path to your custom ``TargetMatchManager`` to the "Target" key of the MATCH_MANAGERS dictionary as shown in the
example.

Your can the override the default ``TargetMatchManager`` by writing your own in the location you used above.

**Remember** the ``TargetMatchManager`` must contain a ``check_for_fuzzy_match`` function and return a queryset.
See the following example for only checking for exact name matches:

.. code:: python
class CustomTargetMatchManager(models.Manager):
"""
Return Queryset for target with name matching string.
"""
def check_for_fuzzy_match(self, name):
"""
Returns a queryset exactly matching name that is received
:param name: The string against which target names and aliases will be matched.
:return: queryset containing matching Targets. Will return targets even when matched value is an alias.
"""
queryset = Target.objects.filter(name=name)
return queryset
This might be useful if a user is experiencing performance issues when ingesting targets or does not wish to allow for
a target matching to similar strings.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
'django-bootstrap4>=3,<24',
'django-contrib-comments~=2.0', # Earlier version are incompatible with Django >= 3.0
'django-crispy-forms~=2.0',
'crispy-bootstrap4',
'crispy-bootstrap4~=2022.0',
'django-extensions~=3.1',
'django-filter>=21,<24',
'django-gravatar2~=1.4',
Expand Down
10 changes: 10 additions & 0 deletions tom_base/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,16 @@
'tom_observations.facilities.soar.SOARFacility',
]

# Define MATCH_MANAGERS here.
# This is a dictionary with the key set to a given model class name and the value as a dotted module path to the desired
# match manager for the named model.
# See https://tom-toolkit.readthedocs.io/en/latest/targets/target_matcher.html
# For example:
# MATCH_MANAGERS = {
# 'Target': 'custom_code_directory.match_managers.MyCustomTargetMatchManager'
# }
MATCH_MANAGERS = {
}

#
# tom_alerts configuration
Expand Down
4 changes: 1 addition & 3 deletions tom_dataproducts/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ class DataProductUploadForm(forms.Form):
required=False
)
files = forms.FileField(
widget=forms.ClearableFileInput(
attrs={'multiple': True}
)
widget=forms.ClearableFileInput()
)
data_product_type = forms.ChoiceField(
choices=[v for k, v in settings.DATA_PRODUCT_TYPES.items()],
Expand Down
12 changes: 11 additions & 1 deletion tom_targets/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django.db import models, transaction
from django.forms.models import model_to_dict
from django.urls import reverse
from django.utils.module_loading import import_string

from tom_common.hooks import run_hook

Expand Down Expand Up @@ -256,7 +257,16 @@ class Target(models.Model):
)

objects = models.Manager()
matches = TargetMatchManager()
target_match_manager = settings.MATCH_MANAGERS.get('Target', None)
if target_match_manager:
try:
manager = import_string(target_match_manager)
matches = manager()
except (ImportError, AttributeError):
raise ImportError(f'Could not import {target_match_manager}. Did you provide the correct path in '
f'settings.py?')
else:
matches = TargetMatchManager()

@transaction.atomic
def save(self, *args, **kwargs):
Expand Down
4 changes: 2 additions & 2 deletions tom_targets/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,9 +325,9 @@ def test_none_extra(self):
self.assertTrue(TargetExtra.objects.filter(target=target, key='foo').exists())

def test_datetime_warning(self):
'''Tests for an int that might come in and get mistakenly parsed for a datetime
"""Tests for an int that might come in and get mistakenly parsed for a datetime
If the value can be successfully cast as a float it is not useful to us as a datetime
Casting a datetime from an int will indicate that year on an arbitrary day. '''
Casting a datetime from an int will indicate that year on an arbitrary day. """
target = SiderealTargetFactory.create()
target.save(extras={'foo': '1984'})
te = target.targetextra_set.get(key='foo')
Expand Down

0 comments on commit a14fb52

Please sign in to comment.