Passing result fields to templates

When rendering search results, it is sometimes useful to transform them into a more human-readable format before rendering to a template. (for example: parsing dates or generating links) It may also be useful to fetch “special” fields that will enable built in functionality. For example the Django Globus Portal Framework includes built-in search result templates which will automatically render if a search result contains specific field names:

  • title – A title for a given subject, shown on the search results page and the detail page.

  • globus_app_link – A link to the file on https://app.globus.org.

  • https_url – A direct-download link to the file.

You can control what fields are presented to the Django templates, and how these fields are retrieved, using fields. The syntax allows you to specify how to find a field either by name, or a retrieval/formatter function.

Warning

Search result templates will always receive two values: ‘all’ (the entire parsed JSON search result) and ‘subject’ (the subject ID for the index). Any other template variables must be explicitly specified in the fields configuration block. This means that you must explicitly specify how to find special template fields such as ‘globus_app_link’.

First, let’s take a look at the metadata once more:

{
    "ingest_type": "GMetaList",
    "ingest_data": {
        "gmeta": [
            {
                "id": "metadata",
                "subject": "globus://ddb59af0-6d04-11e5-ba46-22000b92c6ec/share/godata/file1.txt",
                "visible_to": ["public"],
                "content": {
                    "title": "File Number 1",
                    "url": "globus://ddb59af0-6d04-11e5-ba46-22000b92c6ec/share/godata/file1.txt",
                    "author": "Data Researcher",
                    "tags": ["globus", "tutorial", "file"],
                    "date": "2022-11-15T12:31:28.560098",
                    "times_accessed": 23974,
                    "original_collection_name": "Globus Tutorial Endpoint 1"
                }
            }
        ]
    }
}

Create an empty myportal/fields.py file next to settings.py, and copy-paste the following code.

import os
from urllib.parse import urlsplit, urlunsplit, urlencode


def globus_app_link(result):
    """A Globus Webapp link for the transfer/sync button on the detail page"""
    url = result[0]["url"]
    parsed = urlsplit(url)
    query_params = {
        "origin_id": parsed.netloc,
        "origin_path": os.path.dirname(parsed.path),
    }
    return urlunsplit(
        ("https", "app.globus.org", "file-manager", urlencode(query_params), "")
    )


def https_url(result):
    """Add a direct download link to files over HTTPS"""
    path = urlsplit(result[0]["url"]).path
    return urlunsplit(("https", "g-71c9e9.10bac.8443.data.globus.org", path, "", ""))

Here the result[0] variable encapsulates the information of a given search record, and can be used to access any component of the metadata content such as title and url.

To propagate myportal/fields.py throughout your portal, configure fields for your search index by adding fields to your SEARCH_INDEXES:

from myportal import fields

SEARCH_INDEXES = {
    "index-slug": {
        "uuid": "my-search-index-uuid",
        **options,  # Other options hidden for brevity
        "fields": [
            # Several syntaxes are available for retrieving a field

            # Fetch the field by name, where the name in the search index matches the name used in the template
            "title",

            # Calls a function with your search record as a parameter
            ("globus_app_link", fields.globus_app_link),
            ("https_url", fields.https_url)

            ## Field retrieval/formatters can also be used with custom fields for custom templates
            # Can fetch a field by alias. Works with flat or nested objects!
            ("some_template_field", "original_name_in_search_index"),
            ("another_template_field", "nested.path.to.field"),
        ],
    }
}

You should notice the following changes the next time you run your server:

Continue on to cover custom Templates.