Theme
Version
GitHubPyPIDiscord
On this page

Extension hooks

Extensions hook into the component lifecycle by subclassing ComponentExtension and implementing the on_* methods below. Each hook receives a single context object whose fields are listed under Available data.

Hooks

on_component_class_created

on_component_class_created(ctx: OnComponentClassCreatedContext) -> None

See source code

Called when a new Component class is created.

This hook is called after the Component class is fully defined but before it's registered.

Use this hook to perform any initialization or validation of the Component class.

Example

from django_components import ComponentExtension, OnComponentClassCreatedContext

class MyExtension(ComponentExtension):
    def on_component_class_created(self, ctx: OnComponentClassCreatedContext) -> None:
        # Add a new attribute to the Component class
        ctx.component_cls.my_attr = "my_value"

Available data

FieldTypeDescription
component_clstype[Component]The created Component class

on_component_class_deleted

on_component_class_deleted(ctx: OnComponentClassDeletedContext) -> None

See source code

Called when a Component class is being deleted.

This hook is called before the Component class is deleted from memory.

Use this hook to perform any cleanup related to the Component class.

Example

from django_components import ComponentExtension, OnComponentClassDeletedContext

class MyExtension(ComponentExtension):
    def on_component_class_deleted(self, ctx: OnComponentClassDeletedContext) -> None:
        # Remove Component class from the extension's cache on deletion
        self.cache.pop(ctx.component_cls, None)

Available data

FieldTypeDescription
component_clstype[Component]The to-be-deleted Component class

on_component_data

on_component_data(ctx: OnComponentDataContext) -> None

See source code

Called when a Component was triggered to render, after a component's context and data methods have been processed.

This hook is called after Component.get_template_data(), Component.get_js_data() and Component.get_css_data().

This hook runs after on_component_input.

Use this hook to modify or validate the component's data before rendering.

Example

from django_components import ComponentExtension, OnComponentDataContext

class MyExtension(ComponentExtension):
    def on_component_data(self, ctx: OnComponentDataContext) -> None:
        # Add extra template variable to all components when they are rendered
        ctx.template_data["my_template_var"] = "my_value"

Available data

FieldTypeDescription
componentComponentThe Component instance that is being rendered
component_clstype[Component]The Component class
component_idstrThe unique identifier for this component instance
context_datadictDeprecated. Use template_data instead. Will be removed in v1.0.
template_datadictDictionary of template data from Component.get_template_data()
js_datadictDictionary of JavaScript data from Component.get_js_data()
css_datadictDictionary of CSS data from Component.get_css_data()

on_component_input

on_component_input(ctx: OnComponentInputContext) -> str | None

See source code

Called when a Component was triggered to render, but before a component's context and data methods are invoked.

Use this hook to modify or validate component inputs before they're processed.

This is the first hook that is called when rendering a component. As such this hook is called before Component.get_template_data(), Component.get_js_data(), and Component.get_css_data() methods, and the on_component_data hook.

This hook also allows to skip the rendering of a component altogether. If the hook returns a non-null value, this value will be used instead of rendering the component.

You can use this to implement a caching mechanism for components, or define components that will be rendered conditionally.

Warning

When any extension short-circuits a component (by returning a non-null value), the rest of that component's render is skipped, including on_component_data and on_component_rendered.

Extensions run in order, and the built-in extensions (including the cache) run before user extensions. So your on_component_input may run even when a later extension short-circuits the same component.

In practice this means: if you save something at the start of a render (here, in on_component_input) so you can use or remove it later in on_component_rendered, that later hook might never run. And if you saved it in a dictionary that lives on your extension, nothing ever removes that entry, so the dictionary grows by one with every skipped render. That is a memory leak.

To avoid this, store anything you need for a single render on the component itself, or on something that lives only as long as the component (such as its config object for your extension, or Slot.extra). It is then discarded automatically once the component is done, whether or not on_component_rendered runs.

Example

from django_components import ComponentExtension, OnComponentInputContext

class MyExtension(ComponentExtension):
    def on_component_input(self, ctx: OnComponentInputContext) -> None:
        # Add extra kwarg to all components when they are rendered
        ctx.kwargs["my_input"] = "my_value"

Warning

In this hook, the components' inputs are still mutable.

As such, if a component defines Args, Kwargs, Slots types, these types are NOT yet instantiated.

Instead, component fields like Component.args, Component.kwargs, Component.slots are plain list / dict objects.

Available data

FieldTypeDescription
componentComponentThe Component instance that received the input and is being rendered
component_clstype[Component]The Component class
component_idstrThe unique identifier for this component instance
argslistList of positional arguments passed to the component
kwargsdictDictionary of keyword arguments passed to the component
slotsdict[str, Slot]Dictionary of slot definitions
contextContextThe Django template Context object

on_component_registered

on_component_registered(ctx: OnComponentRegisteredContext) -> None

See source code

Called when a Component class is registered with a ComponentRegistry.

This hook is called after a Component class is successfully registered.

Example

from django_components import ComponentExtension, OnComponentRegisteredContext

class MyExtension(ComponentExtension):
    def on_component_registered(self, ctx: OnComponentRegisteredContext) -> None:
        print(f"Component {ctx.component_cls} registered to {ctx.registry} as '{ctx.name}'")

Available data

FieldTypeDescription
registryComponentRegistryThe registry the component was registered to
namestrThe name the component was registered under
component_clstype[Component]The registered Component class

on_component_rendered

on_component_rendered(ctx: OnComponentRenderedContext) -> str | None

See source code

Called when a Component was rendered, including all its child components.

Use this hook to access or post-process the component's rendered output.

This hook works similarly to Component.on_render_after():

  1. To modify the output, return a new string from this hook. The original output or error will be ignored.

  2. To cause this component to return a new error, raise that error. The original output and error will be ignored.

  3. If you neither raise nor return string, the original output or error will be used.

Example

Change the final output of a component:

from django_components import ComponentExtension, OnComponentRenderedContext

class MyExtension(ComponentExtension):
    def on_component_rendered(self, ctx: OnComponentRenderedContext) -> str | None:
        # Append a comment to the component's rendered output
        return ctx.result + "<!-- MyExtension comment -->"

Cause the component to raise a new exception:

from django_components import ComponentExtension, OnComponentRenderedContext

class MyExtension(ComponentExtension):
    def on_component_rendered(self, ctx: OnComponentRenderedContext) -> str | None:
        # Raise a new exception
        raise Exception("Error message")

Return nothing (or None) to handle the result as usual:

from django_components import ComponentExtension, OnComponentRenderedContext

class MyExtension(ComponentExtension):
    def on_component_rendered(self, ctx: OnComponentRenderedContext) -> str | None:
        if ctx.error is not None:
            # The component raised an exception
            print(f"Error: {ctx.error}")
        else:
            # The component rendered successfully
            print(f"Result: {ctx.result}")

Available data

FieldTypeDescription
componentComponentThe Component instance that is being rendered
component_clstype[Component]The Component class
component_idstrThe unique identifier for this component instance
resultstr | NoneThe rendered component, or None if rendering failed
errorException | NoneThe error that occurred during rendering, or None if rendering was successful

on_component_unregistered

on_component_unregistered(ctx: OnComponentUnregisteredContext) -> None

See source code

Called when a Component class is unregistered from a ComponentRegistry.

This hook is called after a Component class is removed from the registry.

Example

from django_components import ComponentExtension, OnComponentUnregisteredContext

class MyExtension(ComponentExtension):
    def on_component_unregistered(self, ctx: OnComponentUnregisteredContext) -> None:
        print(f"Component {ctx.component_cls} unregistered from {ctx.registry} as '{ctx.name}'")

Available data

FieldTypeDescription
registryComponentRegistryThe registry the component was unregistered from
namestrThe name the component was registered under
component_clstype[Component]The unregistered Component class

on_css_loaded

on_css_loaded(ctx: OnCssLoadedContext) -> str | None

See source code

Called when a Component's CSS is loaded as a string.

This hook runs only once per Component class and works for both Component.css and Component.css_file.

Use this hook to read or modify the CSS.

To modify the CSS, return a new string from this hook.

Example

from django_components import ComponentExtension, OnCssLoadedContext

class MyExtension(ComponentExtension):
    def on_css_loaded(self, ctx: OnCssLoadedContext) -> str | None:
        # Modify the CSS
        return ctx.content.replace("Hello", "Hi")

Available data

FieldTypeDescription
component_clstype[Component]The Component class whose CSS was loaded
contentstrThe CSS content (string)

on_dependencies

on_dependencies(ctx: OnDependenciesContext) -> tuple[list[Script], list[Style]] | None

See source code

Called when a rendered HTML is being finalized, after all dependencies (JS and CSS) were collected, and before they are rendered as <script> and <link> tags.

Use this hook to access or modify the JS/CSS dependencies, for example to:

  • Modify or add dependencies
  • Render <script> tags JS modules with type="module"
  • Add CSP nonce to the dependencies

To modify the dependencies, return a tuple of (scripts, styles).

Where:

  • scripts is a list of Script objects.
  • styles is a list of Style objects.

Example

from django_components import (
    ComponentExtension,
    OnDependenciesContext,
    Script,
    Style,
)

class MyExtension(ComponentExtension):
    def on_dependencies(self, ctx: OnDependenciesContext) -> tuple[list["Script"], list["Style"]]:
        scripts = ctx.scripts
        styles = ctx.styles

        # Modify existing scripts and styles
        for script in scripts:
            if script.kind == "extra":
                script.wrap = False
        for style in styles:
            if style.kind == "extra":
                style.attrs["media"] = "print"

        # Add extra JS and CSS dependencies (inline content)
        scripts.append(
            Script(
                content="console.log('extension-injected script');",
                wrap=False,
            )
        )
        styles.append(
            Style(
                content="body { background-color: red; }",
            )
        )
        # Add extra JS and CSS dependencies (external URL)
        scripts.append(
            Script(
                url="/static/analytics.js",
                content=None,
            )
        )
        styles.append(
            Style(
                url="/static/print.css",
                content=None,
                attrs={"media": "print"},
            )
        )
        return (scripts, styles)

Available data

FieldTypeDescription
scriptslist[Script]List of JS scripts to load
styleslist[Style]List of CSS styles to load

on_extension_created

on_extension_created(ctx: OnExtensionCreatedContext) -> None

See source code

Called when a new ComponentExtension instance is created.

Use this hook to perform any initialization or validation of the extension instance.

Example

from django_components import ComponentExtension, OnExtensionCreatedContext

class MyExtension(ComponentExtension):
    def on_extension_created(self, ctx: OnExtensionCreatedContext) -> None:
        # Add a new attribute to the extension instance
        ctx.extension.my_attr = "my_value"

Available data

FieldTypeDescription
extensionComponentExtensionThe created extension

on_js_loaded

on_js_loaded(ctx: OnJsLoadedContext) -> str | None

See source code

Called when a Component's JS is loaded as a string.

This hook runs only once per Component class and works for both Component.js and Component.js_file.

Use this hook to read or modify the JS.

To modify the JS, return a new string from this hook.

Example

from django_components import ComponentExtension, OnCssLoadedContext

class MyExtension(ComponentExtension):
    def on_js_loaded(self, ctx: OnJsLoadedContext) -> str | None:
        # Modify the JS
        return ctx.content.replace("Hello", "Hi")

Available data

FieldTypeDescription
component_clstype[Component]The Component class whose JS was loaded
contentstrThe JS content (string)

on_registry_created

on_registry_created(ctx: OnRegistryCreatedContext) -> None

See source code

Called when a new ComponentRegistry is created.

This hook is called after a new ComponentRegistry instance is initialized.

Use this hook to perform any initialization needed for the registry.

Example

from django_components import ComponentExtension, OnRegistryCreatedContext

class MyExtension(ComponentExtension):
    def on_registry_created(self, ctx: OnRegistryCreatedContext) -> None:
        # Add a new attribute to the registry
        ctx.registry.my_attr = "my_value"

Available data

FieldTypeDescription
registryComponentRegistryThe created ComponentRegistry instance

on_registry_deleted

on_registry_deleted(ctx: OnRegistryDeletedContext) -> None

See source code

Called when a ComponentRegistry is being deleted.

This hook is called before a ComponentRegistry instance is deleted.

Use this hook to perform any cleanup related to the registry.

Example

from django_components import ComponentExtension, OnRegistryDeletedContext

class MyExtension(ComponentExtension):
    def on_registry_deleted(self, ctx: OnRegistryDeletedContext) -> None:
        # Remove registry from the extension's cache on deletion
        self.cache.pop(ctx.registry, None)

Available data

FieldTypeDescription
registryComponentRegistryThe to-be-deleted ComponentRegistry instance

on_slot_rendered

on_slot_rendered(ctx: OnSlotRenderedContext) -> str | None

See source code

Called when a {% slot %} tag was rendered.

Use this hook to access or post-process the slot's rendered output.

To modify the output, return a new string from this hook.

Example

from django_components import ComponentExtension, OnSlotRenderedContext

class MyExtension(ComponentExtension):
    def on_slot_rendered(self, ctx: OnSlotRenderedContext) -> str | None:
        # Append a comment to the slot's rendered output
        return ctx.result + "<!-- MyExtension comment -->"

Access slot metadata:

You can access the {% slot %} tag node (SlotNode) and its metadata using ctx.slot_node.

For example, to find the Component class to which belongs the template where the {% slot %} tag is defined, you can use ctx.slot_node.template_component:

from django_components import ComponentExtension, OnSlotRenderedContext

class MyExtension(ComponentExtension):
    def on_slot_rendered(self, ctx: OnSlotRenderedContext) -> str | None:
        # Access slot metadata
        slot_node = ctx.slot_node
        slot_owner = slot_node.template_component
        print(f"Slot owner: {slot_owner}")

Available data

FieldTypeDescription
componentComponentThe Component instance that contains the {% slot %} tag
component_clstype[Component]The Component class that contains the {% slot %} tag
component_idstrThe unique identifier for this component instance
slotSlotThe Slot instance that was rendered
slot_namestrThe name of the {% slot %} tag
slot_nodeSlotNodeThe node instance of the {% slot %} tag
slot_is_requiredboolWhether the slot is required
slot_is_defaultboolWhether the slot is default
resultSlotResultThe rendered result of the slot

on_template_compiled

on_template_compiled(ctx: OnTemplateCompiledContext) -> None

See source code

Called when a Component's template is compiled into a Template object.

This hook runs only once per Component class and works for both Component.template and Component.template_file.

Use this hook to read or modify the template (in-place) after it's compiled.

Example

from django_components import ComponentExtension, OnTemplateCompiledContext

class MyExtension(ComponentExtension):
    def on_template_compiled(self, ctx: OnTemplateCompiledContext) -> None:
        print(f"Template origin: {ctx.template.origin.name}")

Available data

FieldTypeDescription
component_clstype[Component]The Component class whose template was loaded
templateTemplateThe compiled template object

on_template_loaded

on_template_loaded(ctx: OnTemplateLoadedContext) -> str | None

See source code

Called when a Component's template is loaded as a string.

This hook runs only once per Component class and works for both Component.template and Component.template_file.

Use this hook to read or modify the template before it's compiled.

To modify the template, return a new string from this hook.

Example

from django_components import ComponentExtension, OnTemplateLoadedContext

class MyExtension(ComponentExtension):
    def on_template_loaded(self, ctx: OnTemplateLoadedContext) -> str | None:
        # Modify the template
        return ctx.content.replace("Hello", "Hi")

Available data

FieldTypeDescription
component_clstype[Component]The Component class whose template was loaded
contentstrThe template string
originOrigin | NoneThe origin of the template
namestr | NoneThe name of the template

Objects

OnComponentClassCreatedContext

Fields

FieldTypeDescription
component_clstype[Component]The created Component class

OnComponentClassDeletedContext

Fields

FieldTypeDescription
component_clstype[Component]The to-be-deleted Component class

OnComponentDataContext

Fields

FieldTypeDescription
componentComponentThe Component instance that is being rendered
component_clstype[Component]The Component class
component_idstrThe unique identifier for this component instance
context_datadictDeprecated. Use template_data instead. Will be removed in v1.0.
template_datadictDictionary of template data from Component.get_template_data()
js_datadictDictionary of JavaScript data from Component.get_js_data()
css_datadictDictionary of CSS data from Component.get_css_data()

OnComponentInputContext

Fields

FieldTypeDescription
componentComponentThe Component instance that received the input and is being rendered
component_clstype[Component]The Component class
component_idstrThe unique identifier for this component instance
argslistList of positional arguments passed to the component
kwargsdictDictionary of keyword arguments passed to the component
slotsdict[str, Slot]Dictionary of slot definitions
contextContextThe Django template Context object

OnComponentRegisteredContext

Fields

FieldTypeDescription
registryComponentRegistryThe registry the component was registered to
namestrThe name the component was registered under
component_clstype[Component]The registered Component class

OnComponentRenderedContext

Fields

FieldTypeDescription
componentComponentThe Component instance that is being rendered
component_clstype[Component]The Component class
component_idstrThe unique identifier for this component instance
resultstr | NoneThe rendered component, or None if rendering failed
errorException | NoneThe error that occurred during rendering, or None if rendering was successful

OnComponentUnregisteredContext

Fields

FieldTypeDescription
registryComponentRegistryThe registry the component was unregistered from
namestrThe name the component was registered under
component_clstype[Component]The unregistered Component class

OnCssLoadedContext

Fields

FieldTypeDescription
component_clstype[Component]The Component class whose CSS was loaded
contentstrThe CSS content (string)

OnDependenciesContext

Fields

FieldTypeDescription
scriptslist[Script]List of JS scripts to load
styleslist[Style]List of CSS styles to load

OnExtensionCreatedContext

Fields

FieldTypeDescription
extensionComponentExtensionThe created extension

OnJsLoadedContext

Fields

FieldTypeDescription
component_clstype[Component]The Component class whose JS was loaded
contentstrThe JS content (string)

OnRegistryCreatedContext

Fields

FieldTypeDescription
registryComponentRegistryThe created ComponentRegistry instance

OnRegistryDeletedContext

Fields

FieldTypeDescription
registryComponentRegistryThe to-be-deleted ComponentRegistry instance

OnSlotRenderedContext

Fields

FieldTypeDescription
componentComponentThe Component instance that contains the {% slot %} tag
component_clstype[Component]The Component class that contains the {% slot %} tag
component_idstrThe unique identifier for this component instance
slotSlotThe Slot instance that was rendered
slot_namestrThe name of the {% slot %} tag
slot_nodeSlotNodeThe node instance of the {% slot %} tag
slot_is_requiredboolWhether the slot is required
slot_is_defaultboolWhether the slot is default
resultSlotResultThe rendered result of the slot

OnTemplateCompiledContext

Fields

FieldTypeDescription
component_clstype[Component]The Component class whose template was loaded
templateTemplateThe compiled template object

OnTemplateLoadedContext

Fields

FieldTypeDescription
component_clstype[Component]The Component class whose template was loaded
contentstrThe template string
originOrigin | NoneThe origin of the template
namestr | NoneThe name of the template
django-components version: 0.152.0