TexturePacker's custom exporter format

Custom Exporters have saved me dozens of hours. I can't function without TexturePacker. Richard Jarell

TexturePacker comes with many different data output formats - both generic formats like JSON and XML, as well as platform-specific formats like Cocos2D, Sparrow, and others.

However, sometimes these built-in formats aren't sufficient - either because your game framework requires its own specific format, or because the existing formats don't meet your particular needs.

The solution is to create your own custom format. This process is easier than you might think - just follow the instructions below to get started.

Modifying an existing exporter

Many of the exporters are available in the TexturePacker folder:

  • Windows users look under C:/Program Files/CodeAndWeb/TexturePacker/resources/exporters
  • Mac users go to /Applications/TexturePacker.app/Contents/Resources/exporters

The plain exporter may be a good starting point. Make sure to duplicate the exporter folder to somewhere outside TexturePacker's installation path and rename the folder and the exporter contents as shown below!

Creating a new exporter from scratch

That's of course possible too... but modifying an existing exporter is the recommended way.

Preparations before creating your own exporter

First, create a directory - it's the Exporter Directory that will contain all your custom exporters - e.g. my-TP-Exporters .

Now create a new subdirectory inside that directory - name it like the exporter you want to create - e.g. testexporter .

Your folder structure should now look like this:

TexturePacker Documentation: Custom exporter - folder structure preparations for export

Set the path to your exporter directory my-TP-Exporters in TexturePacker's preferences and then quit TexturePacker.

TexturePacker Documentation: Custom exporter - Preferences

Structure of an exporter

An exporter consists of 2 or more files:

  • exporter.xml - the file describing the capabilities of the exporter

  • template.txt - the template for the output file format

Optional:

  • filter.qs - one (or more) file(s) to extend the template file with JavaScript

The exporter description file

Create an exporter.xml inside your testexporter directory, or use an exporter.xml of an existing exporter as starting point

Here's an example file, containing descriptions for all supported elements:

<exporter version="1.0"> <!-- file format version, must be 1.0 -->

    <!-- Identifier for the exporter - should be unique.
         This value is stored when the exporter is referenced from a saved file (.tps).
         It is also used to select the exporter from command line.
         Change this if you've duplicated an existing exporter -->
    <name>testexporter</name>

    <!-- Old exporter identifiers (optional); if a tps file with such an id is opened,
         its id is automatically changed to the one specified in <name> -->
    <nameAlias>otherexporter</nameAlias>

    <!-- Name of the exporter that is shown in the framework selector dialog -->
    <!-- Change this if you duplicated an existing exporter -->
    <displayName>TestExporter</displayName>

    <!-- A description of the exporter -->
    <description>My first custom exporter for TexturePacker</description>

    <!-- Exporter version -->
    <version>1.0</version>

    <files>

        <!-- A list of data files which should be generated during the publish process -->
        <file>

            <!-- name of this file type; used in the tps file
                 and by the commandline client: for each MYDATA file
                 a commandline option "- -MYDATA-file" is evaluated
                 (remark: write the option without the blank between the "-" signs,
                 it's required in the XML comment)  -->
            <name>mydata</name>

            <!-- human-readable name (used in the TexturePacker GUI) -->
            <displayName>MyDataFile</displayName>

            <!-- file extension, without '.' -->
            <fileExtension>txt</fileExtension>

            <!-- description what the file contains,
                 used for tooltips in the GUI (optional) -->
            <description>My txt custom exporter for TexturePacker</description>

            <!-- name of the template file -->
            <template>testexporter.txt</template>

            <!-- this file is optional, i.e. if the user does not specify an
                 output file name, the file will not be generated;
                 (optional, default is 'false') -->
            <optional>false</optional>

            <!-- specifies for which scaling variant this data file is generated:
                 all:   for each variant  (default)
                 first: only for the first variant
                 last:  only for the last one   -->
            <hasSeparateAutoSDFiles>all</hasSeparateAutoSDFiles>

            <!-- create a file for each multipack sheet
                 (optional, default is 'true') -->
            <hasSeparateMultiPackFiles>true</hasSeparateMultiPackFiles>

        </file>

        <!-- add more <file> ... </file> tags if you need more than one output file -->
    </files>

    <!-- the following elements show/hide the corresponding input fields -->
    <!-- in the TexturePacker user interface -->

    <!-- mandatory flags: -->

    <!-- Set this to true if the target framework supports trimmed sprites (sprites with
         transparency removed). TexturePacker delivers the offsets and size of the
         trimmed sprite to the template system. The user can still choose to disable
         trimming from the user interface. If supportsTrimming is set to false the option
         to enable trimming is not available in the user interface. -->
    <supportsTrimming>true</supportsTrimming>

    <!-- Set this to true if the target framework supports rotated sprites. The user can
         still decide not to enable rotated sprites from the user interface.
         If supportsRotation is set to false the option to enable sprite rotation is
         not available in the user interface. -->
    <supportsRotation>true</supportsRotation>

    <!-- The direction in which a sprite is rotated - if TexturePacker decides
         to rotate a sprite:
             cw:  clockwise rotation
             ccw: counterclockwise rotation
         The amount of rotation is always 90°. Only required for supportsRotation=true -->
    <rotationDirection>cw</rotationDirection>

    <!-- If enabled TexturePacker allows the user to choose non-power-of-2 sizes for sprite
         sheets. Otherwise, only power-of-2 (POT) sizes are enabled in the user interface. -->
    <supportsNPOT>true</supportsNPOT>

    <!-- the following flags are optional: -->

    <!-- framework supports tightly packed textures, i.e. it can extract sprites
         from a sheet using polygon paths instead of bounding boxes (default=false) -->
    <supportsPolygonPacking>true</supportsPolygonPacking>

    <!-- target framework supports pivot point settings (default=false) -->
    <supportsPivotPoint>false</supportsPivotPoint>

    <!-- target framework accepts sprite names without file name extension. (default=false) -->
    <supportsTrimSpriteNames>true</supportsTrimSpriteNames>

    <!-- framework can read in border values for 9-patch scaling of sprites (default=false) -->
    <supportsScale9>true</supportsScale9>

    <!-- enables the "Auto-detect animations" checkbox in the UI; the implementation of
         an animation detection must be done by the exporter (default=false) -->
    <supportsAnimations>true</supportsAnimations>

    <!-- origin of the coordinate system of a sprite in the target framework,
         needed for pivot point placement. (default=TopLeft) -->
    <spriteOrigin>TopLeft</spriteOrigin> <!-- TopLeft or BottomLeft -->

    <!-- ensure that width/height of generated texture is multiple of this factor (default=1) -->
    <textureSizeFactor>1</textureSizeFactor>

    <!-- ensures that the center offset caused by trimming has integral
         coordinates (default=false)-->
    <ensureIntegerCenterOffset>false</ensureIntegerCenterOffset>

    <!-- You can specify default values for the following TexturePacker settings.
         They are used if a new project is created or if the data format of
         an existing project is changed and "Update to recommended values"
         is checked. The complete <defaults> block is optional. -->
    <defaults>
        <extrude>0</extrude>
        <shapePadding>1</shapePadding>
        <borderPadding>1</borderPadding>
        <trimMode>Polygon</trimMode>               <!-- None, Trim, Crop, CropKeepPos, Polygon -->
        <sizeConstraints>POT</sizeConstraints>     <!-- POT, WordAligned, AnySize -->
        <writePivotPoints>true</writePivotPoints>  <!-- true, false -->
        <defaultPivotPoint>0.0,0.0</defaultPivotPoint>
    </defaults>

    <!-- TexturePacker's "scaling variants" dialog provides a set of presets.
         These presets can be overwritten by exporter-specific ones.
         You can define them with an optional <variantPresets> block as shown here: -->
    <variantPresets>
        <variantPreset>
            <name>HD / SD</name>
            <variant>
                <scale>1.0</scale>
                <extension>-2x</extension>
                <filter></filter>    <!-- optional -->
            </variant>
            <variant>
                <scale>0.5</scale>
                <extension></extension>
                <filter></filter>
            </variant>
            <forceIdenticalLayout>true</forceIdenticalLayout>
        </variantPreset>
    </variantPresets>

    <!-- The following <properties> block shows how to define custom exporter properties.
         For each property TexturePacker displays an input field in the UI.
         The values entered there are stored in the TPS file and passed to the
         exporter when publishing. There they can be used in the template file. -->
    <properties>
        <property>
            <!-- Property name, used in tps file + exporter template: -->
            <name>sprite-prefix</name>
            <!-- Property type, supported values: string, bool -->
            <type>string</type>
            <!-- Default value for new projects -->
            <default>img_</default>
            <!-- Name and tooltip text used for the input field in the UI: -->
            <displayName>Sprite prefix</displayName>
            <toolTip>Prefix for the sprite's name.</toolTip>
            <!-- Only displayed if advanced settings are expanded (small triangle
                 in front of Data settings) -->
            <isAdvanced>true</isAdvanced>
        </property>
        <!-- more <property>s can be defined here -->
    </properties>

</exporter>

The template file

The template file contains a prototype of the data file to write with some additional markup to format the text, build loops and decisions.

If you copied the data from the example file above, you should now create a testexporter.txt in the same directory as the exporter.xml. The file extension of the template file does not matter. However, it might be useful to give it the same extension as the Data file to enable syntax highlighting in your favorite text editor.

TexturePacker uses the Grantlee template engine - which is similar to Django templates. The template syntax is described in detail at the end of this document.

This example template file will write a data file containing a list of sprites with frame coordinates, a flag for rotation and the source coordinates:

// Created with TexturePacker (https://www.codeandweb.com/texturepacker)
//
// Sprite sheet: {{ texture.fullName }} ({{ texture.size.width }} x {{ texture.size.height }})
//
// {{ smartUpdateKey }}

sprites = [
{% for sprite in allSprites %}
    {{ sprite.trimmedName }} = [
        frame = [
            {{ sprite.frameRect.x }},
            {{ sprite.frameRect.y }},
            {{ sprite.frameRect.width }},
            {{ sprite.frameRect.height }}
        ],
        rotated = {{ sprite.rotated }},
        source = [
            {{ sprite.cornerOffset.x }},
            {{ sprite.cornerOffset.y }},
            {{ sprite.untrimmedSize.width }},
            {{ sprite.untrimmedSize.height }}
        ]
    ] {% if not forloop.last %}, {% endif %}
{% endfor %}
]

Using Values in Templates

Values in templates are enclosed within double curly braces: {{ variable }}. To access nested properties within a structure, use the dot notation: {{ object.property }}.

You can apply filters to format values by using the pipe character. For example:

  • {{ x|floatformat:3 }} formats a floating point value with 3 decimal places
  • {{ text|upper }} converts text to uppercase
  • {{ list|join:", " }} joins list items with commas

Control Structures

Templates support several control structures that affect the rendering flow:

Conditionals

{% if condition %}
    Content to render when condition is true
{% else %}
    Content to render when condition is false
{% endif %}

Loops

{% for item in itemList %}
    Content to render for each item
    Current item: {{ item }}
{% endfor %}

Values and data types

The variables that can be used in the template file are described in detail in the table below:

ElementTypeInfo
smartUpdateKeySTRINGhash string over all file dates, used to speed up export
dataAbsoluteFileNameSTRINGabsolute file name of the current data file
settingsSETTINGScontains tps file settings
variantIndexINT0 for hasSeparateAutoSDFiles=first
variantCount-1 for hasSeparateAutoSDFiles=last
[0..variantCount-1] for hasSeparateAutoSDFiles=all
multiPackIndexINT-1 for hasSeparateMultiPackFiles=false
[0..textureCount-1] for multipack textures
variantParamsVARIANTPARAMSsettings adapted for the current scaling variant
allResultsRESULT[]
textureTEXTUREcurrent texture (only available if hasSeparateMultiPackFiles=true)
spritesSPRITE[]sprites (without aliases) of the current texture (or of complete result, if hasSeparateMultiPackFiles=false)
allSpritesSPRITE[]sprites (including aliases) of the current texture (or of complete result, if hasSeparateMultiPackFiles=false)
exporterProperties.MYPROPSTRING or BOOLContains the value of the custom exporter property MYPROP . Exporter properties can defined in the exporter description file, using the <property> element.
tpHASHContains all elements described above. If you want to write your exporter in Javascript you can use this hash to pass all settings to a Javascript function.

The template file is loaded with a set of parameters created during the packing process. The values can be referenced using the template language.

smartUpdateKey

When publishing a spritesheet, TexturePacker checks if the Data file already exists. If the file is found, its contents are read, and a text sequence is searched for - $TexturePacker:SmartUpdate:....hashvalue....$. This value is a hash calculated from all file dates, sizes, and the parameters used to create the texture. If the calculated hash is identical to the current state of the files, no output is created, which speeds up batch operations.

To use this smart update feature, add smartUpdateKey somewhere in the template file. Ensure that the value is placed within a comment or another suitable location to avoid confusing the module reading the data.

sprites and allSprites

The sprites list contains unique sprites only, excluding alias sprites (sprites that contain the same image). To reference alias sprites, you can access a sprite's .aliasList property. On the other hand, allSprites contains a list of all sprites, including alias sprites. In most cases, using allSprites is more convenient than sprites.

The standard way to iterate over the sprites is using

{% for sprite in allSprites %}
    ...
{% endfor %}

SETTINGS

This data type holds .tps file settings.

ElementTypeInfo
autoSDSettings[0..variantCount-1]AUTOSDSETTINGS[]Scaling variant settings
ditherTypenone-nn
none-linear
fs
fs-alpha
atkinson
atkinson-alpha
for more info see Dithering
textureFormatSTRINGtexture format
outputFormatSTRINGoutput format
contentProtection.keySTRING32 hex digits
tpsNameSTRINGname of the tps file
allowRotationBOOLrotation enabled
flipPVRBOOLflip PVR
forceIdenticalLayoutBOOLforce layout to be identical for all variants
multiPackBOOLmultipack enabled
trimSpriteNamesBOOLtrim sprite names
autoAliasEnabledBOOLautomatic detection of duplicate sprites enabled
premultiplyAlphaBOOLpremultiply alpha enabled
reduceBorderArtifactsBOOLreduce border artifacts enabled
fixedTextureSizeSIZEhave a fixed texture size
dataFormatSTRINGdata format
textureSubPathSTRINGtexture sub path
borderPaddingINTborder padding
shapePaddingINTshape padding
commonDivisorXINTcommon divisor X
commonDivisorYINTcommon divisor Y
backgroundColorINTbackground color
writePivotPointsBOOLuser has enabled pivot points
autodetectAnimationsBOOLuser has activated animation detection

AUTOSDSETTINGS

This data type holds AutoSD settings.

ElementTypeInfo
scaleFLOATscaling factor
extensionSTRINGvariant name
spriteFilterSTRINGsprite filter
acceptFractionalValuesBOOLaccept fractional values if no common factor can be found
maxTextureSizeSIZEmaximum texture size

RESULT

Structure containing a packing result.

ElementTypeInfo
texturesTEXTURE[]array of all textures
nonFittingSpritesSTRING[]array containing names of non-fitting sprites

TEXTURE

This data type holds a texture with all its parameters.

ElementTypeInfo
sizeSIZEThe width/height of the Texture file in pixels.
trimmedNameSTRINGThe name of the Texture file - without the extension.
fullNameSTRINGThe name of the Texture file with the extension.
absoluteFileNameSTRINGThe absolute path to the Texture file.
normalMapFileNameSTRINGThe path of the corresponding normal map sheet, relative to texture file.
normalMapAbsoluteFileNameSTRINGThe absolute path of the corresponding normal map sheet.
sprites[0..n]SPRITE[]The sprites on the current texture, without aliases.
allSprites[0..m]SPRITE[]All sprites on current texture, including aliases.
areaINTArea of the texture in pixels (i.e. width*height).

SPRITE

This data type holds a sprite with all its parameters.

ElementTypeInfo
fileDataFILEDATAsprite file data
sizeSIZEsize of the trimmed sprite in pixels, including extrude; typically not needed by exporters
frameRectRECTposition and size of the trimmed sprite on the texture (without extrude, w/h swapped if sprite was rotated)
frameRectWithoutRotationRECTposition of the trimmed sprite on the texture, unrotated size
frameRectRelRECTsame as frameRect, but with coordinates divided by texture size -> value range (0..1)
sourceRectRECTsize of the trimmed sprite, x/y values = cornerOffset, see below
cornerOffsetPOINToffset from the top-left corner of the orignal sprite to the top-left corner of the trimmed sprite (0,0 for Crop, flush pos)
untrimmedSizeSIZEsize of the original, untrimmed sprite (Crop modes: size of trimmed sprite)
trimmedBOOLtrue if sprite is trimmed
rotatedBOOLtrue if sprite is rotated
isSolidBOOLtrue if sprite has no transparent pixels
trimmedNameSTRINGThe name of the sprite file - without the extension.
fullNameSTRINGThe name of the sprite file with the extension.
nameSTRINGtrimmedName or fullName, depending on Trim sprite names flag.
aliasList[0..n]SPRITE[]contains the list of identical sprites
centerOffsetPOINTCenter offset
pivotPointPOINTx and y coordinates of the Pivot Point
pivotPointNormPOINTPivot point coordinates, relative to the sprite size
verticesPOINT[]Polygon points approximating the outline of the sprite. Sprite coordinate system.
verticesUVPOINT[]Polygon points approximating the outline of the sprite. Texture coordinate system.
triangleIndicesINT[]Triangulation of the sprite's polygon. The values in this list are indices in the vertices / verticesUV array.
scale9EnabledBOOLUser enabled 9-patch scaling for this sprite
scale9BordersRECTThe 9-patch borders.
scale9PaddingsRECTThe 9-patch paddings.
scaleFLOATThe sprite's scaling factor as set in Sprite settings. Does not take global/variant scale in account.

The two figures below illustrate the interpretation of the exported elements sourceRect and frameRect:

texturepacker exporter: sourceRect
texturepacker exporter: frameRect

FILEDATA

This data type holds a file.

ElementTypeInfo
absoluteFileNameSTRINGabsolute path of the file
fileSizeFLOATsize of the file
createdDATEcreation date of the file
lastModifiedDATElast modified date of the file

VARIANTPARAMS

This data type holds the settings adapted for the current scaling variant.

ElementTypeInfo
scaleFLOATScaling factor
shapePaddingINTshape padding in pixels
borderPaddingINTborder padding in pixels
commonDivisorXINTCommon Divisor X
commonDivisorYINTCommon Divisor Y
extrudeINTExtrude in pixels
baseFactorINTCommon base factor of all scaling variants
maxTextureSizeSIZEMaximum texture size in pixels
fixedTextureSizeSIZEFixed texture size in pixels

RECT (Rectangle)

ElementTypeInfo
xINTx coordinate
yINTy coordinate
widthINTwidth in pixels
heightINTheight in pixels

POINT

ElementTypeInfo
xINTx coordinate
yINTy coordinate

SIZE

ElementTypeInfo
widthINTwidth in pixels
heightINTheight in pixels

Enhancing the Exporter with JavaScript

While templates are powerful, sometimes you need more advanced functionality - such as complex calculations or data transformations. In these cases, you can enhance your exporter with JavaScript.

Setting Up JavaScript Support

To add JavaScript capabilities to your exporter:

  1. Create two nested directories inside your exporter folder:
    • First create a grantlee directory
    • Then create a 0.2 directory inside it

Your folder structure should look like this:

TexturePacker Documentation: Custom exporter - folder structure
  1. Place your JavaScript file(s) in the grantlee/0.2 directory
  2. Use the .qs extension for your JavaScript files

Creating JavaScript Filters

In your JavaScript file, you can create filters - functions that process template values. A filter:

  1. Receives a value from the template
  2. Processes or transforms that value
  3. Returns the result, which is then included in the output

Here's an example of a filter that converts CSS class selectors to proper CSS syntax:

// Define the filter function
var MakeSelectorFilter = function(input) {
    // Convert the input to a regular JavaScript string
    var input = input.rawString();

    // Process the string (replace "-hover" with ":hover")
    return input.replace("-hover", ":hover");
};

// Set the filter name (this is how it will be referenced in templates)
MakeSelectorFilter.filterName = "makecssselector";

// Register the filter with the template system
Library.addFilter("MakeSelectorFilter");

Important Notes:

  • Converting Input: Always convert the input parameter to a regular JavaScript string using .rawString() before using JavaScript string methods like split() or replace().

  • Return Type: Filters must return a string value.

  • Conditional Filters: To create a filter that evaluates a condition, return an empty string "" for false or any non-empty string (like "true") for true. Then use it in templates like: {% if variable|testfunction %}

Using JavaScript Filters in Templates

Loading Filters

To use a JavaScript filter in your template, you first need to load it:

{% load makecssselector %}

Important: The value in the load tag must match the JavaScript file name (without the .qs extension).

Applying Filters

Once loaded, you can apply the filter to any value in your template by using the pipe character:

{{ sprite.trimmedName|makecssselector }}

This passes the value of sprite.trimmedName to your filter function and includes the result in the output.

Advanced Techniques

Working with Multiple Parameters

Since filters can only receive one parameter directly, you can use these techniques to work with multiple values:

Technique 1: Using Global Variables

You can use one filter to store a value in a global variable, then use another filter to perform calculations with it:

// Define a global variable
width = 1;

// First filter: stores a value for later use
var SetWidth = function (input) {
    width = input; // store the value globally
    return ""; // return empty string (won't appear in output)
};
SetWidth.filterName = "setWidth";
Library.addFilter("SetWidth");

// Second filter: uses the stored global value
var MakeRelX = function (input) {
    return String(input / width); // calculate relative position
};
MakeRelX.filterName = "makeRelX";
Library.addFilter("MakeRelX");

In your template, use these filters in sequence:

{{ texture.size.width|setWidth }}{{ sprite.frameRect.x|makeRelX }}

The first filter (setWidth) stores the texture width but outputs nothing. The second filter (makeRelX) uses that stored width to calculate a relative position.

Creating JavaScript-Only Exporters

For complex exporters, you might prefer to handle most of the work in JavaScript rather than in templates. This approach offers several advantages:

  • More powerful data processing capabilities
  • Better control over output formatting
  • Easier maintenance for complex exporters
  • Native JSON generation without template syntax issues

To create a JavaScript-only exporter, use a minimal template that passes all TexturePacker data to your JavaScript function:

"testexporter.txt"
{% load testexporter %}{{ tp|exportData|safe }}

This template:

  1. Loads your JavaScript file (testexporter.qs)
  2. Passes the entire TexturePacker data structure (tp) to your exportData filter
  3. Uses the safe filter to prevent HTML escaping of the output

Then, in your JavaScript file, you can process the data and generate the output format:

"testexporter.qs"
// Process sprite data
var exportSprites = function(sprites) {
    var result = {};
    for (var i = 0; i < sprites.length; i++) {
        var s = sprites[i];
        var frame = [
            s.frameRect.x, 
            s.frameRect.y, 
            s.frameRect.width, 
            s.frameRect.height
        ];
        result[s.trimmedName] = frame;
    }
    return result;
}

// Process texture data
var exportTextures = function(root) {
    var textures = root.allResults[root.variantIndex].textures;
    var result = {};

    for (var i = 0; i < textures.length; i++) {
        var textureName = textures[i].fullName;
        var sprites = exportSprites(textures[i].allSprites);
        result[textureName] = sprites;
    }

    return result;
}

// Main export function - creates the final output
var exportData = function(root) {
    var doc = exportTextures(root);
    // Generate properly formatted JSON with indentation
    return JSON.stringify(doc, null, "\t");
}

// Register the filter
exportData.filterName = "exportData";
Library.addFilter("exportData");

This example creates a JSON output with texture names as keys, each containing sprite frame data. Using JSON.stringify() ensures valid JSON formatting with proper indentation.

Syntax of the Templates

The syntax of templates contains four types of tokens:

  • Plain text
  • Comments
  • Variables
  • Control tags

A simple template might look like this:

{# A simple template example #}
Hello {{ person.name }},

{% if person.hasBirthday %}
Happy Birthday!
{% else %}
Have a nice day!
{% endif %}

Bye,
{{ myname }}
  • Content inside {# #} are comments and are not part of the output.
  • Content inside {{ }} are variables which are substituted when the template is rendered.
  • Content inside {% %} are control tags which can affect the rendering of the template.

TexturePacker and PhysicsEditor both support commonly used tags such as if, for, cycle and a host of others (see https://docs.djangoproject.com/en/dev/ref/templates/builtins/). It is also possible to define your own custom tags.

Loops

The type of a variable determines how it can be used in templates. For example, treatment of items in an iterable context works as follows:

Lists work as expected:

{% for item in mylist %}
- {{ item }}
{% endfor %}

Truthiness

Truthiness of a variable is evaluated in a similar way to Python. That is:

  • An empty string is false
  • 0 is false
  • An empty list is false
  • Boolean false is false

Everything else is true.

{% if mylist %}
List items:
{% for item in mylist %}
- {{ item }}
{% endfor %}
{% else %}
The list is empty.
{% endif %}

Variable Lookups

So far we've mostly used simple variable lookups in variable tags, but the template system is capable of a lot more. Complex structures can be evaluated using the dot (.) character.

The dot can be used for list index lookup (note that list lookup is 0-indexed):

The first item is {{ mylist.0 }}, and the fifth item is {{ mylist.4 }}.

It can also be used for key lookups:

The hash value is {{ myhash.mykey }}.

And it can retrieve properties from object instances:

The object property is {{ myobj.myprop }}.

Filters

Filters can further affect the result of including a variable in a template. Filters are separated by the pipe (|) character.

Name is {{ name }}, and name in uppercase is {{ name|upper }}.

Which is rendered as:

Name is Alice, and name in uppercase is ALICE.

Note that filters may be combined with dot-lookup. For example, if people is a list of Person objects, and Person objects have name properties:

First person's name: {{ people.0.name|upper }}.

Rendered as:

First person's name: BOB.

Filters may also be chained. Here, 'Claire' is first uppercased, then lowercased:

Name is {{ name|upper|lower }}

Rendered as:

Name is claire.

Filters may take one string argument, which is delimited by a colon (:).

If peoplestring contains "Dave and Ellen and Frank", we can cut the string and :

The people are {{ peoplestring|cut:"and " }}

Rendered as:

The people are Dave Ellen Frank.

Internal filters include:

  • upper - Converts text to uppercase
  • lower - Converts text to lowercase
  • slice - Returns a slice of the list
  • truncate - Truncates a string
  • join - Joins a list with a string
  • split - Splits a string into a list

For more filters, see the Django template built-in filters documentation.

Auto-Escaping in Templates

When creating HTML output, it's necessary to consider escaping data inserted into the template. HTML escaping involves replacing characters like < with &lt; and & with &amp; to prevent them from being interpreted as HTML markup. The template engine automatically escapes string input before adding it to the output.

This is relevant when writing a variable from the context into the template.

If the context object companies is a list containing (Burger King, Ben & Jerries, Ford), and it is used in a template such as:

{% for company in companies %}
- {{ company }}
{% endfor %}

The output would be:

  • Burger King
  • Ben &amp; Jerries
  • Ford

Notice that the & has been replaced with &amp;, as is appropriate for HTML output.

Use the |safe filter to get the unescaped content of the string:

{% for company in companies %}
- {{ company|safe }}
{% endfor %}

It is also possible to turn this auto-escaping feature off for a block in a template:

{% autoescape off %}
...
{% endautoescape %}

This would not escape the content between the autoescape and endautoescape tags. This should only be used for content which is actually already safe.

For more information, see the Django template auto-escaping documentation.