# Template Tag Guide

# attrsortkey

The {% attrsortkey %} template tag is used to create an alias to a specific category attribute, which can then be used for sorting with the sort filter. This is only applicable when sorting an RHNodeQuery instance. For example:

{% attrsortkey "My Category" "My Attribute" as "alias" %}

The category reference can be a DataID, nickname, or identifier. The attribute reference can be an attribute name, ID, or identifier. Once defined it can be used for sorting:

{{ nodes|sort:"-alias"}}

Sorting is applied at the database level by joining the underlying database query with the LLAttrData table.

# block

The {% block %} tag defines a section of a page that can be overridden by another template that extends it. See the {% extends %} tag for more details.

# cache

The {% cache %} template tag is used to cache a fragment of content. Caching is used to improve performance by not having to render the same block on each request.


{% cache %}
	// some content that takes long to compute
{% endcache %}

This renders, caches, and displays the block on the first request. Subsequent requests uses the cached value and takes milliseconds to render. The cache expiry defaults to one hour, but this can be changed with an expiration time parameter.

{% cache 60 %}
	// some content that takes long to compute
	// this cache would last 60 seconds
{% endcache %}

The cache also accepts additional parameters to uniquely identify the cache fragment. This is important whenever a cached block depends on a variable or some other value that could change. For example, say a block depends on the sort parameter and the child nodes of an object. This can be accounted for as follows:

{% cache 3600 request.sort node.lastmodifydatechildren %}
	// some content that takes long to compute
	// this cache would last 3600 seconds and is specific to the sort parameter and the child nodes.
	// the cache will be invalidated once either changes, causing the block
	// to be rendered and cached again
{% endcache %}

In this example the cache is reset whenever the request.sort parameter changes or a child node is modified.

# cleanslate

The {% cleanslate %} template tag removes all Content Server user interface elements from the page.

This tag may not reside within another block tag, and is usually the first line of the template.

The tag accepts an optional parameter to change the mimetype of the response.


{% cleanslate "text/plain" %}

The tag also accepts a third parameter to force a filename when downloading to the desktop.


{% cleanslate "text/plain" "filename.txt" %}

Content variables can also be used in the parameters:

{% cleanslate "text/csv" node.name|add:".csv" %}

# comment

Prevents anything between {% comment %} and {% endcomment %} from being output.


This will be output.

{% comment %}
    This will not be output.
{% endcomment %}

# context

Outputs the context as an HTML table. Useful for debugging.

# currenturl

The currenturl tag returns the current URL, but also gives the option to modify or add query parameters. The syntax is:

{% currenturl parm1 value1 parm2 value2 ... parmN valueN %}

This could be used to create paging links. For example, suppose the current page URL is:


To create a similar URL to page 6:

{% currenturl "page" 6 %}
> http://mydomain.com/livelink/cs.exe?func=ll&objAction=RunReport&objId=12345&page=6

# cycle

Cycles among the arguments each time the tag is encountered. Arguments can include literals or variables.


{% for o in some_list %}
	<tr class="{% cycle 'row1' 'row2' %}">
{% endfor %}

The example is with two arguments, but more arguments are supported.

# dbcache

The dbcache template tag has the same interface as cache, but stores the value in the database.

# debug

Outputs the context as an HTML table. Useful for debugging.

# extends

This tag cannot be placed within any other block, which includes a {% comment %} block.

# filter

The {% filter %} template tag is used to apply a filter to a block.

For example, to apply an upper filter to a block of text:

{% filter upper %}
	My name is Chris
{% endfilter %}


Filters can also be chained.

{% filter upper|replace:"CHRIS":"BOB" %}
	My name is Chris
{% endfilter %}


# for

Loop over each element in the List, RecArray, or Iterator. For example:

{% set "2000"|node as ews %}

{% for item in ews.children|sort:name %}
    <li>{{ item.name }}</li>
{% endfor %}

The loop accepts an optional {% empty %} block that will display if the loop is empty or invalid:

{% set "2000"|node as ews %}

{% for item in ews.children|sort:name %}
    <li>{{ item.name }}</li>
{% empty %}
    <li>Nothing to see here!</li>
{% endfor %}

A forloop variable is visible within the loop and provides context on the current iteration:

  • forloop.counter - the 1-based iteration count of the loop
  • forloop.counter0 - the 0-based iteration count of the loop
  • forloop.first - returns true on the first iteration of the loop, false otherwise
  • forloop.last - returns true on the last iteration of the loop, false otherwise
  • forloop.count - returns the number of items being looped

The Assoc datatype is also supported. The key,value must not have any spaces:

{% for key,value in myAssoc %}
	{{ key }} - {{ value }}<br />
{% endfor %}

# hiddenrequestfield

Creates hidden form fields using the values found in the current request. A form field will only be created if the argument is in the request. For example:

{% hiddenrequestfield "func" "objAction" "fieldNameNotInRequest" %}

This returns something as follows:

<input type="hidden" name="func" value="ll" />
<input type="hidden" name="objAction" value="rhtemplaterun" />

# hiddenrequestfieldexclude

Create a hidden field for each parameter in the request. For example:

{% hiddenrequestfieldsexclude %}

This would return something like:

<input type="hidden" name="func" value="ll" />
<input type="hidden" name="objAction" value="rhtemplaterun" />
<input type="hidden" name="objId" value="12345" />

Fields can be excluded by adding them to the tag. For example, to exclude the func parameter:

{% hiddenrequestfieldsexclude "func" %}

# if

The {% if %} template tag is used to create conditional statements. The tag accepts one or more arguments, and outputs the block if it evaluates to true.


{# Execute a LiveReport (based on a Nickname) and save the contents as "rows" #}
{% set "MyLiveReport"|runreport as rows %}

{% if rows %}
	Your report contains content
{% endif %}

This returns "Your report contains content" if rows has at least one record.

Single expessions to the {% if %} tag evaluate to true under the following conditions:

  • Booleans with a true value;
  • Integers with a non zero value;
  • RecArrays or Lists with a length greater than 0; and
  • Strings with length greater than 0 (exceptions listed below).

Single expessions evaluate to false under the following conditions:

  • Booleans with false value;
  • Integers with value 0;
  • RecArrays or Lists with length 0;
  • Strings with length 0;
  • Strings with value "false", "no", or "0";
  • Undefined values; and
  • Errors.

The tag also supports {% elif %} and {% else %} blocks, and expressions can be compounded with or and and. Compounded statements are evaluated from left to right.


{% set "MyLiveReport"|runreport as rows %}
{% set "MyOtherLiveReport"|runreport as rows2 %}

{% if rows and rows2 %}
	Both reports have content
{% elif rows %}
	Only MyLiveReport has content
{% elif rows2 %}
	Only MyOtherLiveReport has content
{% else %}
	Neither reports have content
{% endif %}

Single expressions can be negated with the not keyword:

{% if not rows %}
	Your report has no content
{% endif %}

Comparitive expressions are supported with the following boolean operators. Operators listed here on the same line are synonymous:

  • equals, equal, is, ==, =
  • notequals, notequal, !=, <>
  • equallessthan, <=, =<
  • equalgreaterthan, >=, =>
  • lessthan, <
  • greaterthan, >
  • in, within, memberof

For example:

{% if user.name == "Admin" %}
	Welcome Admin!  Nice to see you again.
{% else %}
	Welcome {{ user.name }}.
{% endif %}

Single and comparitive expressions can be mixed.

{% if user.name == "Admin" and not rows %}
	Welcome Admin!  Your report contains no rows.
{% elif not rows %}
	No rows.
{% else %}
	Welcome {{ user.name }}
{% endif %}

# ifchanged

# ifequal

The {% ifequal %} template tag is a conditional statement that accepts two arguments. It outputs the block if the arguments are equal. For example:

{% ifequal user.name "Admin" %}
	Welcome Admin!
{% endifequal %}

This is functionally equivalent to:

{% if user.name == "Admin %}
	Welcome Admin!
{% endif %}

Use the if template tag if a more complex conditional statement is required.

# ifnotequal

The {% ifnotequal %} template tag is a conditional statement that accepts two arguments. It outputs the block if the arguments are not equal. For example:

{% ifnotequal user.name "Admin" %}
	You are not Admin.
{% endifnotequal %}

This is functionally equivalent to:

{% if user.name != "Admin %}
	You are not Admin.
{% endif %}

Use the if template tag if a more complex conditional statement is required.

# include

Opens a template and renders it with the current context. Context variables can be altered within an included template, but only new template variables are preserved.

Templates can be referenced in one of three ways:

  • by DataID;
  • by identifier;
  • by nickname; or
  • by file path (e.g., modulename/filename.html).

The nickname is the preferred method to reference a template within the system. Nicknames can be kept consistent among Content Server instances, which makes moving a template among instances much easier.


{% include "rhcore/macros.html" %}

This would load and render the contents of rhtemplate/macros.html.

The contents of the template can also be saved to a context variable by using the as keyword.


{% include "MyTemplateNickname" as myVariable %} // renders no output
{{ myVariable }} // renders the output

Parameters can be passed to a template with the syntax:

{% include "rhtemplate/mytemplate.html" with parm1=value1 parm2=value2 ... parmN=valueN %}

The {% link %} tag is used to generate a request handler link. The syntax is:

{% link rh title arg1 arg2 ... argN %}

For example, to create a URL to the admin.index page:

{% link admin.index "Click here for admin.index" %}

Some request handlers accept arguments, which are defined by the request handler fPrototype feature. You can use the args filter to inspect the parameters of a request handler and the order they are defined.

For example:

{{ 'user.EditUser'|args }}



With this information we can create a user edit link:

{% link user.EditUser "Edit User" 1000 cgi %}

The tag attempts to determine if you are able to execute the request handler based on the request handliner extensions in RHCore.

The {% link_disabled %} tag is identical to {% link %}, but create a disabled link if the URL cannot be resolved for any reason.

For example, trying to link to an unknown request handler will only output the title :

{% link_disabled unknown.rh "Link to Unknown RH" %}
> Link to Unknown RH

# load

Loads data into the context. The parameter defines the data to load, but is also the default context variable name for the loaded data.


To load a user's favourites:

{% load favourites %}

This loads the user's favourites into the context with the variable name favourites. The variable name can also be explicitly set as follows:

{% load favourites as myfavourites %}

Valid parameters to {% load %} are as follows:

  • appbuild -

  • appversion -

  • assignments - Returns the assignments of the current user.

  • csbuild -

  • csbuildinteger -

  • DAPOnScheduleEnum -

  • DAPs -

  • dbtype -

  • defaultpagesize - Returns the default page size.

  • defaultpagesizechoices -

  • documentregistry -

  • dossiers -

  • dossierstatefacetid -

  • enums -

  • eol -

  • ews - Returns an RHNode representation of the Enterprise Workspace.

  • favourites - Returns the favourites of the current user.

  • fullcgi -

  • gmessages -

  • guid - Returns a globally unique identifier (GUID).

  • jsdateformat - Returns the JavaScript mask for the system configured date format.

  • jsdatetimeformat - Returns the JavaScript mask for the system configured date and time format.

  • jsmomentdateformat -

  • jsmomentdatetimeformat -

  • jstimeformat - Returns the JavaScript mask for the system configured time format.

  • majorversionnodes - Returns a representation of every node in the system accessible by the current user. Use with care.

  • messages -

  • nodes - Returns a representation of every node in the system accessible by the current user. Use with care.

  • now - Returns the system date and time.

  • otcsticket -

  • otvar -

  • profiler -

  • projects - Returns all projects the current user is a member of.

  • requestargs -

  • reserveditems - Returns all items reserved by the current user.

  • s4 -

  • serverdisplayname - Returns the server display name as configured in the Content Server Administration page.

  • SkyGuideReport1 -

  • workflows -

  • workflows2 -

# macro

Defines a macro that can be called with the usemacro tag. The syntax to define a macro is:

{% macro macroname parm1 parm2 ... parmN %}
   // render your macro with parm1 ... parmN
{% endmacro %}

For example:

The following macro is included with rhcore/macros.html and can be used to generate a Content Server function menu.

{% macro functionmenu item %}
<a href="#" onclick="showFunctionMenu2('nextURL={{ nexturl|escapeurl }}', {{ node.dataid }}, event );return false">
	<img src="{{ support }}webdoc/actions.png" id="x{{ node.dataid }}" border="0" alt="Functions" title="Functions" 
		onmouseover="this.src='{{ support }}webdoc/actions_hover.png'" onmouseout="this.src='{{ support }}webdoc/actions.png'">
<div id="z{{ node.dataid }}" style="min-width:1px; background-color: #eeeeee;" class="functionMenuDiv"></div> %}
{% endmacro %}

This can be rendered with:

{% usemacro functionmenu "2000" %}
> Generates a function menu for the Enerprise Workspace

Macros can call other templates and macros, and some recursion is supported.

# macros

Returns the names of all macros defined in the context.

# markdown

Renders the markdown text between {% markdown %} and {% endmarkdown %} as HTML.

For example:

{% markdown %}
# Header1
* item1
* item2
{% endmarkdown %}

This would output the following:


# now

The now template tag returns the system date and time. It can be optionally formatted by passing a format string as the first parameter. See the Date filter for formatting details.


{% now "%Y" %}
> 2013

# profiler

# regroup

# runonce

# set

# sortkey

The {% sortkey %} template tag is used to alias a verbose sort key, which can then be used with the sort filter.

Sorting is usually applied by passing a sort key in a request parameter:

{% set myItems|sort:request.sort as sortedItems %}

However, this gets messy if the sort parameter is verbose (e.g., node__user__name). This can be simplified with the {% sortkey %} template tag as follows:

{% sortkey "node__user__name" as "username" %}

This declaration makes username a valid parameter to sort, and is evaluated as node__user__name.

# sortkeypath

The {% sortkeypath %} is used to define a keypath with which the sort filter can be applied.

For example, it can be used to sort a node list based on a category value.

{% sortkeypath "categoryvalues.MyCategory.MyAttribute.first" as attr %}

Then in your iterator:

{% for node in nodes|sort:"attr" %}
{% endfor %} 

This is useful when sorting on evaluated properties, but does require evaluating the keypath on each item in the iterator. It is far less efficient than applying the sort at the database level as is done with QuerySets.

# spaceless

# switch

# tabs

The {% tabs %} template tag is used to create HTML tabs. The tag manages the URL creation for each tab and only renders the tab being displayed.


{% tabs %}
	{% tab "Tab 1" %}
		// tab1 content
	{% endtab %}
	{% tab "Tab 2" %}
		// tab2 content
	{% endtab %}
	{% tab "Tab 3" %}
		// tab3 content
	{% endtab %}
{% endtabs %}

This would create the following HTML:

<div class="rhtabs">
		<li class="active"><a class="active" href="/livelink/cs.exe?func=...&tab=1">Tab 1</a></li>
		<li><a href="/livelink/cs.exe?func=...&tab=2">Tab 2</a></li>
		<li><a href="/livelink/cs.exe?func=...&tab=3">Tab 3</a></li>

		// tab1 content

The outer div is wrapped in an rhtabs class, which renders nicely when the rhcore.css stylesheet is included in the page. This class and the tab url parameter can be modified with two optional parameters:


{% tabs "t" "myTabClass" %}

This would render the following:

<div class="myTabClass">
		<li class="active"><a class="active" href="/livelink/cs.exe?func=...&t=1">Tab 1</a></li>
		<li><a href="/livelink/cs.exe?func=...&t=2">Tab 2</a></li>
		<li><a href="/livelink/cs.exe?func=...&t=3">Tab 3</a></li>

		// tab1 content

Each {% tab %} accepts a second parameter that can toggle the visibility of a tab.


Say you want a tab to only display if the current user has administration privileges:

{% tab "Admin Tab" user.isAdmin %}
    Content that only administrators should see.
{% endtab %}

# tick

# title

# trans

# trim

Defines a block where all leading and trailing whitespace is removed.


Some text

{% trim %}

	All white space within the block before and after this line is removed.

{% endtrim %}

# url

# usemacro

# verbatim

# widthratio

# with

Last Updated: 7/19/2019, 3:06:36 PM