<a id="accessing-metadata-and-labels"></a>
<a id="id1"></a>
# Accessing Metadata and Labels

TrialGrid allows [Custom Properties (metadata)](../properties.html.md#properties) and [Labels](../labels.html.md#labels) to be applied to objects. These can be accessed and included in Document Templates.

<a id="custom-properties-metadata"></a>
<a id="accessing-metadata"></a>
## Custom Properties (Metadata)

Objects in the [Object Model Reference](attribute_reference.html.md#attribute-reference) which have a *properties* method may have associated metadata. The *properties* attribute surfaces this data as a python dictionary keyed by the lowercase name of the property.

```jinja
{# Example for getting the value of a custom property called "SDTM Domain" from a set of forms #}
{% for form in draft.als_forms_set.order_by("OID") %}
  Form : {{ form.OID }}
  SDTM Domain : {{ form.properties["sdtm domain"].value }}  {# Note LOWER CASE #}
{% endfor %}
```

Note that objects may not have a value set for a particular metadata value. In that case the value returned will be "" (empty string) if the custom property exists. If a custom property of that name does not exist (i.e has not been defined for the URL or is mispelled), then the template generation will fail with an error.

One way to avoid an error if a custom property does not exist is to use the .get method and provide a fallback value:

```jinja
{{ form.properties.get("no such property", {"value":"Doesn't exist"}).value }}
```

In addition to .value other attributes are also provided:

| Name | Type | Description |
| --- | --- | --- |
| name | string | The name of the Custom Property (with original case, e.g. "SDTM Domain") |
| description | string | The description of the Custom Property |
| display_order | integer | The display order for this Custom Property in relation to other custom properties for this kind of object |
| value | string | The actual value set for the custom property on this object instance |
| is_set | boolean | When an object does not have any value set for a custom property the value is returned as "" (empty string). This flag is set to False when there is no value present for the custom property. |
| value_type | string | One of "boolean", "choice", "color", "date", "datetime", "email", "html", "numeric", "reference", "set", "text", "uri" or "user" |
| value_choices | List of string (or None if value_type is not "choice") | The possible values of a choice type (for value_type = "choice" only) |
| reference_type_id | integer or None | For properties with value_type "reference", the ID of the Custom Object Definition for the referenced object type. This can be used to look up the referenced object. None for non-reference properties. |
| show_in_list | boolean | True if the custom property is set to be shown in object lists, False otherwise |
| include_in_agent_context | boolean | True if the value of this custom property is sent to AI Agents, False otherwise |
| llm_instruction | string | Guidance for AI Agents on how to read the value of this custom property. "" (empty string) if none is set. |

Properties which point at something else hold what they point at, not its name. A "reference" property holds the id of the object it names, and a "user" property holds the id of the person it names. Printing the value of either shows a number.

For a "user" property, pass that value to [user_by_id()](template_context.html.md#template-context) to get the person:

```jinja
{% set owner = user_by_id(form.properties['form owner'].value) %}
{% if owner %}Owner: {{ owner.username }} ({{ owner.email }}){% endif %}
```

Nothing comes back when the property has no value, when the person no longer exists, or when they do not work in this Organization, so test the result before using it.

With this information Templates can include lists of the custom properties defined for an object:

```jinja
{# Use the .values() method of the python dictionary to loop through all the properties available for the object #}
{% for property in draft.Project.properties.values() %}
    <para>{{ property.name }} = {{ property.value }}</para>
    <para>{{ property.description }}</para>
{% endfor %}
```

<a id="labels"></a>
<a id="accessing-labels"></a>
## Labels

URLs may define [Labels](../labels.html.md#labels) which can be applied to objects including Drafts, Projects and Draft Objects (Forms, Edit Checks etc).

Objects which may have associated labels have a *labels* collection which is a list of ObjectLabels. Each ObjectLabel has a reference to the [Label](attribute_reference.html.md#attribute-label) definition so you can get the name, color, description etc:

```jinja
{% for object_label in draft.Project.labels %}
    <para>{{ object_label.label.name }} has color {{ object_label.label.color }}</para>
    <para>Description {{ object_label.label.description }}</para>
{% endfor %}
```
