Tips and Tricks

Solutions to common problems.

The following variables are undefined ...

When saving a Document template you might see this error. The system checks that variables used in the template have been defined so that this would cause an error:

{# my_variable has not been defined anywhere, this is an error #}
{{ my_variable }}

But the system is not perfect. set instructions inside if..endif blocks will cause an error saying that "x" is undefined:

{% if True %}
   {% set x = 1 %}
   {{ x }}
{% endif %}

The workaround for this is to introduce the x variable so that it can be found at the top level:

{# Add this to the variables section at the top of your template file #}
{% set x = None %}

{% if True %}
   {% set x = 1 %}
   {{ x }}
{% endif %}

Working with Date/Times

A number of objects have datetime attributes such as created or updated dates. These are stored as python datetimes in the UTC timezone. You can convert these date/times to the timezone of your choice or use the USER_TIMEZONE_NAME constant which is provided by the users browser when they request the report.

{% for timezone in ["Europe/London", "Asia/Kolkata", USER_TIMEZONE_NAME] %}
    created ({{timezone}})  : {{ ticket.created|timezone(timezone) }}
{% endfor %}

For a list of timezones see Wikipedia Time Zone names

You can also format datetimes using the python strftime formats and the format_datetime filter.

{% for timezone in ["Europe/London", "Asia/Kolkata", USER_TIMEZONE_NAME] %}
    created ({{timezone}})  : {{ ticket.created|timezone(timezone)|format_datetime('%Y-%m-%d %H:%M') }}
{% endfor %}

The current date/time can be accessed via the now() function. This will change every time it is callled (time moves on) so if you want the date/time that the document template task started use the constant GENERATED_AT:

Created at Server Time (UTC): {{ GENERATED_AT|format_datetime('%Y-%m-%d %HH:%M') }}
Created at User: {{ GENERATED_AT|timezone(USER_TIMEZONE_NAME)|format_datetime('%Y-%m-%d %HH:%M') }}
Created at NY: {{ GENERATED_AT|timezone("America/New_York")|format_datetime('%Y-%m-%d %HH:%M') }}

Time now Server (UTC): {{ now()|format_datetime('%Y-%m-%d %HH:%M') }}
Time now User: {{ now()|timezone(USER_TIMEZONE_NAME)|format_datetime('%Y-%m-%d %HH:%M') }}
Time now in NY: {{ now()|timezone("America/New_York")|format_datetime('%Y-%m-%d %HH:%M') }}

Find all Objects by a Custom Property Value

Lets say you define a custom property called "Target Form OID" which is applied to Edit Checks. Now you want to loop through all Form objects and find related Edit Checks which have the custom property value for Target Form OID as the form OID. i.e.:

{% for form in draft.als_forms_set.all() %}
   Form: {{ form.OID }}

   {# Here I want to list all Edit checks that have "Target Form OID" = form.OID. How? #}

{% endfor %}

One way to do this is to use the list of all ObjectProperty values that are related to the Draft. This is the draft.objectproperty_set. An ObjectProperty has a link both to the object to which it is related (e.g. an Edit Check) and to the Draft for ease of lookup.

{% for form in draft.als_forms_set.all() %}
   Form: {{ form.OID }}

   {% for object_property in draft.objectproperty_set.filter(property__name="Target Form OID", value=form.OID) %}
       {% set check = object_property.content_object %}
       Edit Check: {{ check.CheckName }}
   {% endfor %}

{% endfor %}

Note

This is finding all ObjectProperties for all objects which have a property name of "Target Form OID". If a custom property called "Target Form OID" has also been defined for Derivations as well as Edit Checks then this will also find those Derivations and the content_object value will point to a Derivation rather than an Edit Check.

An ObjectProperty is a join between the Draft, the Object to which it is attached and the Property Definition:

Object Property