Digests
This document describes all the data available in Jinja2 templates for email digests.
Table of Contents
- Main Context Variables
- Digest Information
- Equipment Data
- Qualifications Data
- Quotes Data
- Leave Data
- Individual Mode
Main Context Variables
The following top-level variables are always available in your templates:
| Variable | Type | Description |
|---|---|---|
digest |
object | The digest configuration and metadata |
equipment |
object | Equipment calibration data |
qualifications |
object | Staff qualifications data |
quotes |
object | Project quotes and enquiries data |
leave |
object | Leave/vacation data |
today |
date | Current date |
user |
object | Current user (only in individual mode) |
Digest Information
digest object
Contains the digest configuration:
| Field | Type | Description |
|---|---|---|
id |
integer | Unique identifier |
name |
string | Name of the digest |
org |
object | Organization (see below) |
individual |
boolean | Whether individual emails are sent |
subject |
string | Email subject template |
equipment_days_before |
integer | Days before today for equipment data |
equipment_days_after |
integer | Days after today for equipment data |
qualifications_days_before |
integer | Days before today for qualifications |
qualifications_days_after |
integer | Days after today for qualifications |
leave_days_before |
integer | Days before today for leave data |
leave_days_after |
integer | Days after today for leave data |
created |
datetime | Creation timestamp |
created_by |
object | User who created (see User object) |
modified |
datetime | Last modification timestamp |
modified_by |
object | User who modified (see User object) |
digest.org object
| Field | Type | Description |
|---|---|---|
id |
integer | Organization ID |
name |
string | Organization name |
Equipment Data
equipment object
Contains two arrays of equipment items:
| Field | Type | Description |
|---|---|---|
expired |
array | Equipment with expired calibration |
expiring |
array | Equipment with upcoming calibration |
Equipment Item Structure
Each item in equipment.expired or equipment.expiring :
| Field | Type | Description |
|---|---|---|
id |
integer | Equipment ID |
name |
string | Equipment name |
category |
object | Equipment category (id, name) |
serial |
string | Serial number |
calibration |
date | Calibration due date |
identifier |
string | Equipment identifier |
barcode |
string | Barcode value |
Example Usage
{% if equipment.expired %}
<h3>Expired Equipment</h3>
<ul>
{% for item in equipment.expired %}
<li>{{ item.name }} - Expired on {{ item.calibration }}</li>
{% endfor %}
</ul>
{% endif %}
{% if equipment.expiring %}
<h3>Equipment Due for Calibration</h3>
<ul>
{% for item in equipment.expiring %}
<li>{{ item.name }} - Due {{ item.calibration }}</li>
{% endfor %}
</ul>
{% endif %}
Qualifications Data
qualifications object
Contains two arrays of qualification items:
| Field | Type | Description |
|---|---|---|
expired |
array | Expired qualifications |
expiring |
array | Qualifications expiring soon |
Qualification Item Structure
Each item in qualifications.expired or qualifications.expiring :
| Field | Type | Description |
|---|---|---|
id |
integer | Qualification ID |
user |
object | User with qualification (see User object) |
name |
string | Qualification name |
reference |
string | Reference number |
start |
date | Start date |
end |
date | Expiry date |
Example Usage
{% if qualifications.expiring %}
<h3>Qualifications Expiring Soon</h3>
<table>
<tr><th>Employee</th><th>Qualification</th><th>Expires</th></tr>
{% for qual in qualifications.expiring %}
<tr>
<td>{{ qual.user.name }}</td>
<td>{{ qual.name }}</td>
<td>{{ qual.end }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
Quotes Data
quotes object
Contains two arrays of project/quote items:
| Field | Type | Description |
|---|---|---|
created |
array | Enquiries (not yet quoted) |
open |
array | Open quotes (quoted but not decided) |
Quote Item Structure
Each item in quotes.created or quotes.open :
| Field | Type | Description |
|---|---|---|
id |
integer | Project ID |
name |
string | Project name |
reference |
string | Project reference |
client |
object | Client (id, name) |
category |
object | Project category (id, name) |
created |
datetime | Creation date |
created_by |
object | User who created (id, name) |
modified |
datetime | Last modification date |
modified_by |
object | User who modified (id, name) |
quoted |
date | Date quoted (null for enquiries) |
quoted_by |
object | User who quoted (id, name) |
price_net |
decimal | Net price |
currency |
string | Currency code |
deadline |
date | Project deadline |
quote_deadline |
date | Quote validity deadline |
quote_decision |
string | Quote decision status |
Example Usage
{% if quotes.created %}
<h3>New Enquiries</h3>
<ul>
{% for quote in quotes.created %}
<li>
<strong>{{ quote.client.name }}</strong>: {{ quote.name }}
(Created {{ quote.created|date:"Y-m-d" }})
</li>
{% endfor %}
</ul>
{% endif %}
{% if quotes.open %}
<h3>Quotes Awaiting Decision</h3>
<ul>
{% for quote in quotes.open %}
<li>
{{ quote.client.name }}: {{ quote.name }}
- Quoted {{ quote.quoted|date:"Y-m-d" }}
{% if quote.quote_deadline %} (Valid until {{ quote.quote_deadline }}){% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
Leave Data
leave object
Contains two arrays of leave items:
| Field | Type | Description |
|---|---|---|
created |
array | Leave requests pending approval |
approved |
array | Approved leave in date range |
Leave Item Structure
Each item in leave.created or leave.approved :
| Field | Type | Description |
|---|---|---|
id |
integer | Leave ID |
user |
object | Employee (see User object) |
type |
object | Leave type (id, name) |
start |
date | Start date |
end |
date | End date |
days |
decimal | Number of days |
hours |
decimal | Number of hours |
decision |
string | Decision status (empty="Requested", "A"="Approved", "D"="Denied") |
decided |
datetime | When decision was made |
decided_by |
object | Manager who decided (see User object) |
decided_notes |
string | Decision notes |
Example Usage
{% if leave.created %}
<h3>Pending Leave Requests</h3>
<ul>
{% for request in leave.created %}
<li>
{{ request.user.name }} - {{ request.type.name }}
({{ request.start }} to {{ request.end }}, {{ request.days }} days)
</li>
{% endfor %}
</ul>
{% endif %}
{% if leave.approved %}
<h3>Upcoming Leave</h3>
<ul>
{% for absence in leave.approved %}
<li>
{{ absence.user.name }}: {{ absence.start|date:"M d" }} - {{ absence.end|date:"M d" }}
</li>
{% endfor %}
</ul>
{% endif %}
User Object Structure
User objects appear in various places and have this structure:
| Field | Type | Description |
|---|---|---|
id |
integer | User ID |
name |
string | Full name |
email |
string | Email address |
first_name |
string | First name |
last_name |
string | Last name |
Individual Mode
When digest.individual is true , each recipient gets a personalized email with an additional user variable:
user object (only in individual mode)
The full user object for the recipient, containing all user profile data.
Example Usage
{% if user %}
<p>Hello {{ user.first_name }},</p>
<p>Here's your personal digest for {{ today|date:"F j, Y" }}:</p>
{% else %}
<p>Team Digest for {{ today|date:"F j, Y" }}:</p>
{% endif %}
Conditional Display
Use Jinja2 conditionals to show/hide sections:
{% if equipment.expired or equipment.expiring %}
<section class="equipment-section">
<!-- Equipment content -->
</section>
{% endif %}
{% if leave.created|length > 5 %}
<p class="alert">{{ leave.created|length }} leave requests pending!</p>
{% endif %}
Loops and Filters
Common Jinja2 filters useful for digests:
{{ items|length }} <!-- Count items -->
{{ price|floatformat:2 }} <!-- Format decimal -->
{{ text|truncatewords:20 }} <!-- Limit text length -->
{{ value|default:"N/A" }} <!-- Default value -->
{% for item in items|slice:":5" %} <!-- First 5 items -->
<!-- ... -->
{% endfor %}
Complete Example Template
<!DOCTYPE html>
<html>
<head>
<title>{{ digest.org.name }} Digest - {{ today|date:"F j, Y" }}</title>
</head>
<body>
<h1>{{ digest.org.name }} Weekly Digest</h1>
<p>Report generated on {{ today|date:"l, F j, Y" }}</p>
{% if quotes.created or quotes.open %}
<h2>Projects & Quotes</h2>
{% if quotes.created %}
<h3>New Enquiries ({{ quotes.created|length }})</h3>
<ul>
{% for project in quotes.created|slice:":10" %}
<li>{{ project.client.name }}: {{ project.name }}</li>
{% endfor %}
</ul>
{% endif %}
{% if quotes.open %}
<h3>Quotes Pending Decision ({{ quotes.open|length }})</h3>
<ul>
{% for project in quotes.open %}
<li>
{{ project.client.name }}: {{ project.name }}
- {{ project.currency }} {{ project.price_net|floatformat:2 }}
{% if project.quote_deadline %}
(Expires: {{ project.quote_deadline|date:"M d" }})
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
{% endif %}
{% if leave.created or leave.approved %}
<h2>Leave Management</h2>
{% if leave.created %}
<h3>Pending Approvals</h3>
<table>
{% for request in leave.created %}
<tr>
<td>{{ request.user.name }}</td>
<td>{{ request.start|date:"M d" }} - {{ request.end|date:"M d" }}</td>
<td>{{ request.days }} days</td>
</tr>
{% endfor %}
</table>
{% endif %}
{% endif %}
{% if equipment.expired %}
<h2>⚠️ Expired Equipment Calibrations</h2>
<ul>
{% for item in equipment.expired %}
<li>{{ item.name }} ({{ item.category.name }}) - Expired {{ item.calibration }}</li>
{% endfor %}
</ul>
{% endif %}
{% if user %}
<hr>
<p><small>This digest was personalized for {{ user.name }}.</small></p>
{% endif %}
</body>
</html>
Notes for Template Designers
- Always check for data existence before displaying sections to avoid empty headers
- Use the
|lengthfilter to show counts in section headers - Consider using
|sliceto limit long lists in summary views - Format dates consistently throughout the template
- Test with both individual and non-individual modes if your digest supports both
- Remember that
useris only available in individual mode - All date/datetime fields can be null - always check before displaying
Testing Your Templates
To test your templates with sample data:
- Create a test digest in the admin panel
- Set appropriate day ranges for each data type
- Send test emails to verify formatting
- Test both with and without data in each section
- Test individual mode if applicable