Using template variables
Template variables provide a powerful way to make dynamic values and functions available for use when defining components in yaml. Jinja style template injection is applied when loading yaml documents defining component instances, and template variables are the set of things that are available for use in those template expressions.
There are two ways to define template variables:
- Template variables module - Defined as standalone functions in a separate module
- Component class static methods - Defined as
@staticmethod
on a Component class
Template variables module
The template variables module allows for defining functions in a separate module and are associated with a specific path in the component hierarchy. They can optionally accept a ComponentLoadContext
parameter, giving you access to the component's loading context.
Setting up a template variables module
First, create a template_vars.py
file. We will place it adjacent to the defs.yaml
since that is the only place using it, though it could be defined elsewhere:
import os
import dagster as dg
@dg.template_var
def table_prefix() -> str:
if os.getenv("IS_PROD"):
return "warehouse"
else:
return "dev_warehouse"
Then reference the template variables module in your defs.yaml
using Jinja template syntax:
type: my_project.components.DataProcessor
template_vars_module: .template_vars
attributes:
table_name: "{{ table_prefix }}_data"
Module path resolution
The template_vars_module
field supports both relative and absolute module paths:
- Relative paths (starting with
.
) are resolved relative to the current component's module path - Absolute paths specify the full module path
# Relative path (recommended for co-located template vars)
template_vars_module: .template_vars
# Absolute path
template_vars_module: my_project.shared.template_vars
Template variable function signatures
Template variable functions can have different signatures depending on whether they need access to the component loading context:
import dagster as dg
@dg.template_var
def simple_value() -> str:
"""No context needed - returns a static value."""
return "simple_value"
@dg.template_var
def context_aware_value(context: dg.ComponentLoadContext) -> str:
"""Uses context to determine the value."""
return f"value_for_{context.path.name}"
Component class static methods
Template variables can also be defined directly on your Component class using the @template_var
decorator on a @staticmethod
. This approach is useful in cases where you are defining a reusable component and would like all uses of that component to have access to a set of useful template variables
from typing import Callable
import dagster as dg
class MyComponent(dg.Component):
@staticmethod
@dg.template_var
def database_url() -> str:
return "postgresql://localhost:5432/mydb"
@staticmethod
@dg.template_var
def get_table_name() -> Callable:
return lambda prefix: f"{prefix}_processed_data"
You can then use these template variables in your component definition:
type: my_project.components.MyComponent
attributes:
connection_string: "{{ database_url }}"
table_name: "{{ get_table_name('sales') }}"
Important: Static template variables must not take any arguments. They are evaluated once when the class is loaded.