Adding Custom Fields to Targets --- Sometimes you'd like to store data for targets but the predefined fields that the TOM Toolkit provides aren't enough. The TOM Toolkit allows you to define extra fields for your targets so you can associate different kinds of data with them. For example, you might be studying high redshift galaxies. In this case, it would make sense to be able to store the redshift of your targets. You could then do a search for targets with a redshift less than or greater than a particular value, or use the redshift value to make decisions in your science code. **Note**: There is a performance hit when using extra fields. Try to use the built in fields whenever possible. ### Enabling extra fields To start, find the `EXTRA_FIELDS` definition in your `settings.py`: ```python # Define extra target fields here. Types can be any of "number", "string", "boolean" or "datetime" # For example: # EXTRA_FIELDS = [ # {'name': 'redshift', 'type': 'number'}, # {'name': 'discoverer', 'type': 'string'} # {'name': 'eligible', 'type': 'boolean'}, # {'name': 'dicovery_date', 'type': 'datetime'} # ] EXTRA_FIELDS = [] ``` We can define any number of extra fields in the array. Each item in the array is a dictionary with two values: name and type. Name is simply what you would like to name your field. Type is the datatype of the field and can be one of: `number`, `string`, `boolean` or `datetime`. These types allow the TOM Toolkit to properly store, filter and display these values elsewhere. As an example, let's change the setting to look like this: ```python EXTRA_FIELDS = [ {'name': 'redshift', 'type': 'number'}, ] ``` This will make an extra field with the name "redshift" and a type of "number" available to add to our targets. ### Using extra fields Now if you go to the target creation page, you should see the new field available: ![](/_static/target_fields_doc/redshift.png) And if we go to our list of targets, we should see redshift as a field available to filter on: ![](/_static/target_fields_doc/redshift_filter.png) Extra fields with the `number` type allow filtering on range of values. The same goes for fields with the `datetime` type. `string` types to a case insensitive inclusive search, and `boolean` fields to a simple matching comparison. Of course, redshift does appear on our target's display page as well: ![](/_static/target_fields_doc/redshift_display.png) To hide extra fields from the target page, we can set the "hidden" key (this doesn't affect filtering and searching): ```python EXTRA_FIELDS = [ {'name': 'redshift', 'type': 'number', 'hidden': True}, ] ``` And we can set a default value for an extra field by including a default key/value pair: ```python EXTRA_FIELDS = [ {'name': 'redshift', 'type': 'number', 'default': 0}, ] ``` ### Displaying extra fields in templates If we want to display the redshift in other places, we can use a template filter to do that. For example, we might want to display the redshift value in the target list table. At the top of our template make sure to load `targets_extras`: ``` {% raw %} {% load targets_extras %} {% endraw %} ``` Now we can use the `target_extra_field` filter wherever a target object is available in the template context: ``` {% raw %} {{ target|target_extra_field:"redshift" }} {% endraw %} ``` The result is the redshift value being printed on the template: ![](/_static/target_fields_doc/redshift_tag.png) ### Working with extra fields programatically If you'd like to update or save extra fields to your targets in code, there are a few methods you can use. The simplest is to simply pass in a dictionary of extra data to your target's `save()` method using the `extras` keyword argument: ```python target = Target.objects.get(name='example') target.save(extras={'foo': 42}) ``` The example target above will now have an extra field "foo" with the value 42. For more precise control, you can access `TargetExtra` models directly. To remove an extra, for example: ```python target = Target.objects.get(name='example') target_extra = target.targetextra_set.get(key='foo') target_extra.delete() ``` The above deleted the target extra on a target with the key of "foo".