Theme
Version
GitHubPyPIDiscord
On this page

API

AttrsDict

AttrsDict()

Bases: dict

See source code

Reuse composed HTML attributes as both a dictionary and rendered markup.

You will usually create an AttrsDict with compose_attrs() in Python or the {% attrs %} template tag. Use it like a regular dictionary when passing attributes to a component, reading values, or unpacking keyword arguments:

attrs = compose_attrs(
    {"id": "save", "class": "button"},
    {"class": {"active": True}},
)

attrs["id"]
# "save"

str(attrs)
# 'id="save" class="button active"'

In a component template, pass the native dictionary by using {% attrs %} as the only node in a quoted input:

{% component "table" table_attrs="{% attrs base_attrs local_attrs %}" / %}

Unlike {% html_attrs %}, these APIs produce a reusable native dictionary in addition to rendering attributes. AttrsDict, compose_attrs(), and {% attrs %} supersede {% html_attrs %} for attribute composition. Prefer the new APIs in new code; {% html_attrs %} remains supported for backward compatibility.

BaseNode

BaseNode(
    params: list[TagAttr],
    filters: dict[str, Callable[[Any, Any], Any]],
    tags: dict[str, Callable[[Any, Any], Any]],
    flags: dict[str, bool] | None = None,
    nodelist: NodeList | None = None,
    node_id: str | None = None,
    contents: str | None = None,
    template_name: str | None = None,
    template_component: type[Component] | None = None,
    start_tag_source: str | None = None
)

Bases: django.template.base.Node

See source code

Node class for all django-components custom template tags.

This class has a dual role:

  1. It declares how a particular template tag should be parsed - By setting the tag, end_tag, and allowed_flags attributes:

    class SlotNode(BaseNode):
        tag = "slot"
        end_tag = "endslot"
        allowed_flags = ["required"]
    

    This will allow the template tag {% slot %} to be used like this:

    {% slot required %} ... {% endslot %}
    
  2. The render method is the actual implementation of the template tag.

    This is where the tag's logic is implemented:

    class MyNode(BaseNode):
        tag = "mynode"
    
        def render(self, context: Context, name: str, **kwargs: Any) -> str:
            return f"Hello, {name}!"
    

    This will allow the template tag {% mynode %} to be used like this:

    {% mynode name="John" %}
    

The template tag accepts parameters as defined on the render method's signature.

For more info, see BaseNode.render().

Attributes

tag

tag: str

The tag name.

E.g. "component" or "slot" will make this class match template tags {% component %} or {% slot %}.

class SlotNode(BaseNode):
    tag = "slot"
    end_tag = "endslot"

This will allow the template tag {% slot %} to be used like this:

{% slot %} ... {% endslot %}

end_tag

end_tag: str | None

The end tag name.

E.g. "endcomponent" or "endslot" will make this class match template tags {% endcomponent %} or {% endslot %}.

class SlotNode(BaseNode):
    tag = "slot"
    end_tag = "endslot"

This will allow the template tag {% slot %} to be used like this:

{% slot %} ... {% endslot %}

If not set, then this template tag has no end tag.

So instead of {% component %} ... {% endcomponent %}, you'd use only {% component %}.

class MyNode(BaseNode):
    tag = "mytag"
    end_tag = None

allowed_flags

allowed_flags: Iterable[str] | None

The list of all possible flags for this tag.

E.g. ["required"] will allow this tag to be used like {% slot required %}.

class SlotNode(BaseNode):
    tag = "slot"
    end_tag = "endslot"
    allowed_flags = ["required", "default"]

This will allow the template tag {% slot %} to be used like this:

{% slot required %} ... {% endslot %}
{% slot default %} ... {% endslot %}
{% slot required default %} ... {% endslot %}

params

params: list[TagAttr]

The parameters to the tag in the template.

A single param represents an arg or kwarg of the template tag.

E.g. the following tag:

{% component "my_comp" key=val key2='val2 two' %}

Has 3 params:

  • Posiitonal arg "my_comp"
  • Keyword arg key=val
  • Keyword arg key2='val2 two'

start_tag_source

start_tag_source: str | None

The source code of the start tag with parameters as a string.

E.g. the following tag:

{% slot "content" default required %}
  <div>
    ...
  </div>
{% endslot %}

The start_tag_source will be "{% slot "content" default required %}".

May be None if the Node instance was created manually.

flags

flags: dict[str, bool]

Dictionary of all allowed_flags that were set on the tag.

Flags that were set are True, and the rest are False.

E.g. the following tag:

class SlotNode(BaseNode):
    tag = "slot"
    end_tag = "endslot"
    allowed_flags = ["default", "required"]
{% slot "content" default %}

Has 2 flags, default and required, but only default was set.

The flags dictionary will be:

{
    "default": True,
    "required": False,
}

You can check if a flag is set by doing:

if node.flags["default"]:
    ...

filters

filters: dict[str, Callable]

The filters available to the tag.

This will be the same as the global Django filters.

tags

tags: dict[str, Callable]

The tags available to the tag.

This will be the same as the global Django tags.

nodelist

nodelist: NodeList

The nodelist of the tag.

This is the text between the opening and closing tags, e.g.

{% slot "content" default required %}
  <div>
    ...
  </div>
{% endslot %}

The nodelist will contain the <div> ... </div> part.

Unlike contents, the nodelist contains the actual Nodes, not just the text.

contents

contents: str | None

The body of the tag as a string.

This is the text between the opening and closing tags, e.g.

{% slot "content" default required %}
  <div>
    ...
  </div>
{% endslot %}

The contents will be "<div> ... </div>".

node_id

node_id: str

The unique ID of the node.

Extensions can use this ID to store additional information.

template_name

template_name: str | None

The name of the Template that contains this node.

The template name is set by Django's template loaders.

For example, the filesystem template loader will set this to the absolute path of the template file.

"/home/user/project/templates/my_template.html"

template_component

template_component: type[Component] | None

If the template that contains this node belongs to a Component, then this will be the Component class.

active_flagsproperty

active_flags: list[str]

Flags that were set for this specific instance as a list of strings.

E.g. the following tag:

{% slot "content" default required / %}

Will have the following flags:

["default", "required"]

Methods

render

render(
context: Context,
*_args: Any = (),
**_kwargs: Any = {}
) -> str

See source code

Render the node. This method is meant to be overridden by subclasses.

The signature of this function decides what input the template tag accepts.

The render() method MUST accept a context argument. Any arguments after that will be part of the tag's input parameters.

So if you define a render method like this:

def render(self, context: Context, name: str, **kwargs: Any) -> str:

Then the tag will require the name parameter, and accept any extra keyword arguments:

{% component name="John" age=20 %}

parseclassmethod

parse(
parser: Parser,
token: Token,
**kwargs: Any = {}
) -> BaseNode

See source code

This function is what is passed to Django's Library.tag() when registering the tag.

In other words, this method is called by Django's template parser when we encounter a tag that matches this node's tag, e.g. {% component %} or {% slot %}.

To register the tag, you can use BaseNode.register().

registerclassmethod

register(library: Library) -> None

See source code

A convenience method for registering the tag with the given library.

class MyNode(BaseNode):
    tag = "mynode"

MyNode.register(library)

Allows you to then use the node in templates like so:

{% load mylibrary %}
{% mynode %}

unregisterclassmethod

unregister(library: Library) -> None

See source code

Unregisters the node from the given library.

CommandLiteralAction

CommandLiteralAction: TypeAlias

See source code

The basic type of action to be taken when this argument is encountered at the command line.

This is a subset of the values for action in ArgumentParser.add_argument().

Component

Component(
    registered_name: str | None = None,
    outer_context: Context | None = None,
    registry: ComponentRegistry | None = None,
    context: Context | None = None,
    args: Any | None = None,
    kwargs: Any | None = None,
    slots: Any | None = None,
    deps_strategy: DependenciesStrategy | None = None,
    request: HttpRequest | None = None,
    node: ComponentNode | None = None,
    id: str | None = None,
    parent: Component | None = None,
    root: Component | None = None
)

Attributes

Args

Args: type | None

Optional typing for positional arguments passed to the component.

If set and not None, then the args parameter of the data methods (get_template_data(), get_js_data(), get_css_data()) will be the instance of this class:

from django_components import Component

class Table(Component):
    class Args:
        color: str
        size: int

    def get_template_data(self, args: Args, kwargs, slots, context):
        assert isinstance(args, Table.Args)

        return {
            "color": args.color,
            "size": args.size,
        }

Use Args to:

  • Validate the input at runtime.
  • Set type hints for the positional arguments for data methods like get_template_data().
  • Document the component inputs.

You can also use Args to validate the positional arguments for Component.render():

Table.render(
    args=Table.Args(color="red", size=10),
)

If you do not specify any bases, the Args class will be automatically converted to a NamedTuple:

class Args: -> class Args(NamedTuple):

If you explicitly set bases, the constructor of this class MUST accept positional arguments:

Args(*args)

As such, a good starting point is to set this field to a subclass of NamedTuple.

Read more on Typing and validation.

Kwargs

Kwargs: type | None

Optional typing for keyword arguments passed to the component.

If set and not None, then the kwargs parameter of the data methods (get_template_data(), get_js_data(), get_css_data()) will be the instance of this class:

from django_components import Component

class Table(Component):
    class Kwargs:
        color: str
        size: int = 10

    def get_template_data(self, args, kwargs: Kwargs, slots, context):
        assert isinstance(kwargs, Table.Kwargs)

        return {
            "color": kwargs.color,
            "size": kwargs.size,
        }

Use Kwargs to:

  • Validate the input at runtime.
  • Set type hints for the keyword arguments for data methods like get_template_data().
  • Set defaults for individual fields
  • Document the component inputs.

You can also use Kwargs to validate the keyword arguments for Component.render():

Table.render(
    kwargs=Table.Kwargs(color="red", size=10),
)

The defaults set on Kwargs will be merged with defaults from Component.Defaults class. Kwargs takes precendence. Read more about Component defaults.

If you do not specify any bases, the Kwargs class will be automatically converted to a NamedTuple:

class Kwargs: -> class Kwargs(NamedTuple):

If you explicitly set bases, the constructor of this class MUST accept keyword arguments:

Kwargs(**kwargs)

As such, a good starting point is to set this field to a subclass of NamedTuple or a dataclass.

Read more on Typing and validation.

Slots

Slots: type | None

Optional typing for slots passed to the component.

If set and not None, then the slots parameter of the data methods (get_template_data(), get_js_data(), get_css_data()) will be the instance of this class:

from django_components import Component, Slot, SlotInput

class Table(Component):
    class Slots:
        header: SlotInput
        footer: Slot

    def get_template_data(self, args, kwargs, slots: Slots, context):
        assert isinstance(slots, Table.Slots)

        return {
            "header": slots.header,
            "footer": slots.footer,
        }

Use Slots to:

  • Validate the input at runtime.
  • Set type hints for the slots for data methods like get_template_data().
  • Document the component inputs.

You can also use Slots to validate the slots for Component.render():

Table.render(
    slots=Table.Slots(
        header="HELLO IM HEADER",
        footer=Slot(lambda ctx: ...),
    ),
)

If you do not specify any bases, the Slots class will be automatically converted to a NamedTuple:

class Slots: -> class Slots(NamedTuple):

If you explicitly set bases, the constructor of this class MUST accept keyword arguments:

Slots(**slots)

As such, a good starting point is to set this field to a subclass of NamedTuple or a dataclass.

Read more on Typing and validation.

Info

Components can receive slots as strings, functions, or instances of Slot.

Internally these are all normalized to instances of Slot.

Therefore, the slots dictionary available in data methods (like get_template_data()) will always be a dictionary of Slot instances.

To correctly type this dictionary, you should set the fields of Slots to Slot or SlotInput:

SlotInput is a union of Slot, string, and function types.

template_file

template_file: str | None

Filepath to the Django template associated with this component.

The filepath must be either:

  • Relative to the directory where the Component's Python file is defined.
  • Relative to one of the component directories, as set by COMPONENTS.dirs or COMPONENTS.app_dirs (e.g. <root>/components/).
  • Relative to the template directories, as set by Django's TEMPLATES setting (e.g. <root>/templates/).

Warning

Only one of template_file, get_template_name, template or get_template must be defined.

Example

Assuming this project layout:

|- components/
  |- table/
    |- table.html
    |- table.css
    |- table.js

Template name can be either relative to the python file (components/table/table.py):

class Table(Component):
    template_file = "table.html"

Or relative to one of the directories in [COMPONENTS.dirs](../settings/#dirs) or [COMPONENTS.app_dirs](../settings/#app_dirs) (components/):

class Table(Component):
    template_file = "table/table.html"

template_name

template_name: str | None

Alias for template_file.

For historical reasons, django-components used template_name to align with Django's TemplateView.

template_file was introduced to align with js/js_file and css/css_file.

Setting and accessing this attribute is proxied to template_file.

template

template: str | None

Inlined Django template (as a plain string) associated with this component.

Warning

Only one of template_file, template, get_template_name(), or get_template() must be defined.

Example

class Table(Component):
    template = '''
      <div>
        {{ my_var }}
      </div>
    '''

Syntax highlighting

When using the inlined template, you can enable syntax highlighting with django_components.types.django_html.

Learn more about syntax highlighting.

from django_components import Component, types

class MyComponent(Component):
    template: types.django_html = '''
      <div>
        {{ my_var }}
      </div>
    '''

TemplateData

TemplateData: type | None

Optional typing for the data to be returned from get_template_data().

If set and not None, then this class will be instantiated with the dictionary returned from get_template_data() to validate the data.

Use TemplateData to:

  • Validate the data returned from get_template_data() at runtime.
  • Set type hints for this data.
  • Document the component data.

You can also return an instance of TemplateData directly from get_template_data() to get type hints:

from django_components import Component

class Table(Component):
    class TemplateData:
        color: str
        size: int

    def get_template_data(self, args, kwargs, slots, context):
        return Table.TemplateData(
            color=kwargs["color"],
            size=kwargs["size"],
        )

The constructor of this class MUST accept keyword arguments:

TemplateData(**template_data)

A good starting point is to set this field to a subclass of NamedTuple or a dataclass.

Read more on Typing and validation.

Info

If you use a custom class for TemplateData, this class needs to be convertable to a dictionary.

You can implement either:

  1. _asdict() method

    class MyClass:
        def __init__(self):
            self.x = 1
            self.y = 2
    
        def _asdict(self):
            return {'x': self.x, 'y': self.y}
    
  2. Or make the class dict-like with __iter__() and __getitem__()

    class MyClass:
        def __init__(self):
            self.x = 1
            self.y = 2
    
        def __iter__(self):
            return iter([('x', self.x), ('y', self.y)])
    
        def __getitem__(self, key):
            return getattr(self, key)
    

js

js: str | None

Main JS associated with this component inlined as string.

Warning

Only one of js or js_file must be defined.

Example

class MyComponent(Component):
    js = "console.log('Hello, World!');"

Syntax highlighting

When using the inlined template, you can enable syntax highlighting with django_components.types.js.

Learn more about syntax highlighting.

Example

from django_components import Component, types

class MyComponent(Component):
    js: types.js = '''
        console.log('Hello, World!');
    '''

js_file

js_file: str | None

Main JS associated with this component as file path.

The filepath must be either:

  • Relative to the directory where the Component's Python file is defined.
  • Relative to one of the component directories, as set by COMPONENTS.dirs or COMPONENTS.app_dirs (e.g. <root>/components/).
  • Relative to the staticfiles directories, as set by Django's STATICFILES_DIRS setting (e.g. <root>/static/).

When you create a Component class with js_file, these will happen:

  1. If the file path is relative to the directory where the component's Python file is, the path is resolved.
  2. The file is read and its contents is set to Component.js.

Warning

Only one of js or js_file must be defined.

Example

path/to/script.js
console.log('Hello, World!');
path/to/component.py
class MyComponent(Component):
    js_file = "path/to/script.js"

print(MyComponent.js)
# Output: console.log('Hello, World!');

JsData

JsData: type | None

Optional typing for the data to be returned from get_js_data().

If set and not None, then this class will be instantiated with the dictionary returned from get_js_data() to validate the data.

Use JsData to:

  • Validate the data returned from get_js_data() at runtime.
  • Set type hints for this data.
  • Document the component data.

You can also return an instance of JsData directly from get_js_data() to get type hints:

from django_components import Component

class Table(Component):
    class JsData(
        color: str
        size: int

    def get_js_data(self, args, kwargs, slots, context):
        return Table.JsData(
            color=kwargs["color"],
            size=kwargs["size"],
        )

The constructor of this class MUST accept keyword arguments:

JsData(**js_data)

A good starting point is to set this field to a subclass of NamedTuple or a dataclass.

Read more on Typing and validation.

Info

If you use a custom class for JsData, this class needs to be convertable to a dictionary.

You can implement either:

  1. _asdict() method

    class MyClass:
        def __init__(self):
            self.x = 1
            self.y = 2
    
        def _asdict(self):
            return {'x': self.x, 'y': self.y}
    
  2. Or make the class dict-like with __iter__() and __getitem__()

    class MyClass:
        def __init__(self):
            self.x = 1
            self.y = 2
    
        def __iter__(self):
            return iter([('x', self.x), ('y', self.y)])
    
        def __getitem__(self, key):
            return getattr(self, key)
    

css

css: str | None

Main CSS associated with this component inlined as string.

Warning

Only one of css or css_file must be defined.

Example

class MyComponent(Component):
    css = """
        .my-class {
            color: red;
        }
    """

Syntax highlighting

When using the inlined template, you can enable syntax highlighting with django_components.types.css.

Learn more about syntax highlighting.

Example

from django_components import Component, types

class MyComponent(Component):
    css: types.css = '''
      .my-class {
        color: red;
      }
    '''

css_file

css_file: str | None

Main CSS associated with this component as file path.

The filepath must be either:

  • Relative to the directory where the Component's Python file is defined.
  • Relative to one of the component directories, as set by COMPONENTS.dirs or COMPONENTS.app_dirs (e.g. <root>/components/).
  • Relative to the staticfiles directories, as set by Django's STATICFILES_DIRS setting (e.g. <root>/static/).

When you create a Component class with css_file, these will happen:

  1. If the file path is relative to the directory where the component's Python file is, the path is resolved.
  2. The file is read and its contents is set to Component.css.

Warning

Only one of css or css_file must be defined.

Example

path/to/style.css
.my-class {
    color: red;
}
path/to/component.py
class MyComponent(Component):
    css_file = "path/to/style.css"

print(MyComponent.css)
# Output:
# .my-class {
#     color: red;
# };

CssData

CssData: type | None

Optional typing for the data to be returned from get_css_data().

If set and not None, then this class will be instantiated with the dictionary returned from get_css_data() to validate the data.

Use CssData to:

  • Validate the data returned from get_css_data() at runtime.
  • Set type hints for this data.
  • Document the component data.

You can also return an instance of CssData directly from get_css_data() to get type hints:

from django_components import Component

class Table(Component):
    class CssData:
        color: str
        size: int

    def get_css_data(self, args, kwargs, slots, context):
        return Table.CssData(
            color=kwargs["color"],
            size=kwargs["size"],
        )

The constructor of this class MUST accept keyword arguments:

CssData(**css_data)

A good starting point is to set this field to a subclass of NamedTuple or a dataclass.

Read more on Typing and validation.

Info

If you use a custom class for CssData, this class needs to be convertable to a dictionary.

You can implement either:

  1. _asdict() method

    class MyClass:
        def __init__(self):
            self.x = 1
            self.y = 2
    
        def _asdict(self):
            return {'x': self.x, 'y': self.y}
    
  2. Or make the class dict-like with __iter__() and __getitem__()

    class MyClass:
        def __init__(self):
            self.x = 1
            self.y = 2
    
        def __iter__(self):
            return iter([('x', self.x), ('y', self.y)])
    
        def __getitem__(self, key):
            return getattr(self, key)
    

media

media: MediaCls | None

Normalized definition of JS and CSS media files associated with this component. None if Component.Media is not defined.

This field is generated from Component.media_class.

Read more on Accessing component's Media JS / CSS.

Example

class MyComponent(Component):
    class Media:
        js = "path/to/script.js"
        css = "path/to/style.css"

print(MyComponent.media)
# Output:
# <script src="/static/path/to/script.js"></script>
# <link href="/static/path/to/style.css" media="all" rel="stylesheet">

media_class

media_class: type[MediaCls]

Set the Media class that will be instantiated with the JS and CSS media files from Component.Media.

This is useful when you want to customize the behavior of the media files, like customizing how the JS or CSS files are rendered into <script> or <link> HTML tags.

Read more in Media class.

Example

class MyTable(Component):
    class Media:
        js = "path/to/script.js"
        css = "path/to/style.css"

    media_class = MyMediaClass

Media

Media: type[ComponentMediaInput] | None

Defines JS and CSS media files associated with this component.

This Media class behaves similarly to Django's Media class:

  • Paths are generally handled as static file paths, and resolved URLs are rendered to HTML with media_class.render_js() or media_class.render_css().
  • A path that starts with http, https, or / is considered a URL, skipping the static file resolution. This path is still rendered to HTML with media_class.render_js() or media_class.render_css().
  • A SafeString (with __html__ method) is considered an already-formatted HTML tag, skipping both static file resolution and rendering with media_class.render_js() or media_class.render_css().
  • You can set extend to configure whether to inherit JS / CSS from parent components. See Media inheritance.

However, there's a few differences from Django's Media class:

  1. Our Media class accepts various formats for the JS and CSS files: either a single file, a list, or (CSS-only) a dictionary (See ComponentMediaInput).
  2. Individual JS / CSS files can be any of str, bytes, Path, SafeString, or a function (See ComponentMediaInputPath).

Example

class MyTable(Component):
    class Media:
        js = [
            "path/to/script.js",
            "https://unpkg.com/alpinejs@3.14.7/dist/cdn.min.js",  # AlpineJS
        ]
        css = {
            "all": [
                "path/to/style.css",
                "https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css",  # TailwindCSS
            ],
            "print": ["path/to/style2.css"],
        }

response_class

response_class: type[HttpResponse]

This attribute configures what class is used to generate response from Component.render_to_response().

The response class should accept a string as the first argument.

Defaults to django.http.HttpResponse.

Example

from django.http import HttpResponse
from django_components import Component

class MyHttpResponse(HttpResponse):
    ...

class MyComponent(Component):
    response_class = MyHttpResponse

response = MyComponent.render_to_response()
assert isinstance(response, MyHttpResponse)

Cache

The fields of this class are used to configure the component caching.

Read more about Component caching.

Example

from django_components import Component

class MyComponent(Component):
    class Cache:
        enabled = True
        ttl = 60 * 60 * 24  # 1 day
        cache_name = "my_cache"

cache

Instance of ComponentCache available at component render time.

Defaults

The fields of this class are used to set default values for the component's kwargs.

These defaults will be merged with defaults on Component.Kwargs.

Read more about Component defaults.

Example

from django_components import Component, Default

class MyComponent(Component):
    class Defaults:
        position = "left"
        selected_items = Default(lambda: [1, 2, 3])

defaults

Instance of ComponentDefaults available at component render time.

View

The fields of this class are used to configure the component views and URLs.

This class is a subclass of django.views.View. The Component instance is available via self.component.

Override the methods of this class to define the behavior of the component.

Read more about Component views and URLs.

Example

class MyComponent(Component):
    class View:
        def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
            return HttpResponse("Hello, world!")

view

Instance of ComponentView available at component render time.

DebugHighlight

DebugHighlight: type[ComponentDebugHighlight]

The fields of this class are used to configure the component debug highlighting.

Read more about Component debug highlighting.

name

name: str

The name of the component.

If the component was registered, this will be the name under which the component was registered in the ComponentRegistry.

Otherwise, this will be the name of the class.

Example

@register("my_component")
class RegisteredComponent(Component):
    def get_template_data(self, args, kwargs, slots, context):
        return {
            "name": self.name,  # "my_component"
        }

class UnregisteredComponent(Component):
    def get_template_data(self, args, kwargs, slots, context):
        return {
            "name": self.name,  # "UnregisteredComponent"
        }

registered_name

registered_name: str | None

If the component was rendered with the {% component %} template tag, this will be the name under which the component was registered in the ComponentRegistry.

Otherwise, this will be None.

Example

@register("my_component")
class MyComponent(Component):
    template = "{{ name }}"

    def get_template_data(self, args, kwargs, slots, context):
        return {
            "name": self.registered_name,
        }

Will print my_component in the template:

{% component "my_component" / %}

And None when rendered in Python:

MyComponent.render()
# None

id

id: str

This ID is unique for every time a Component.render() (or equivalent) is called (AKA "render ID").

This is useful for logging or debugging.

The ID is a 7-letter alphanumeric string in the format cXXXXXX, where XXXXXX is a random string of 6 alphanumeric characters (case-sensitive).

E.g. c1A2b3c.

A single render ID has a chance of collision 1 in 57 billion. However, due to birthday paradox, the chance of collision increases to 1% when approaching ~33K render IDs.

Thus, there is currently a soft-cap of ~30K components rendered on a single page.

If you need to expand this limit, please open an issue on GitHub.

Example

class MyComponent(Component):
    def get_template_data(self, args, kwargs, slots, context):
        print(f"Rendering '{self.id}'")

MyComponent.render()
# Rendering 'ab3c4d'

input

Deprecated. Will be removed in v1.

Input holds the data that were passed to the current component at render time.

This includes:

  • args - List of positional arguments
  • kwargs - Dictionary of keyword arguments
  • slots - Dictionary of slots. Values are normalized to Slot instances
  • context - Context object that should be used to render the component
  • And other kwargs passed to Component.render() like deps_strategy

Example

class Table(Component):
    def get_template_data(self, args, kwargs, slots, context):
        # Access component's inputs, slots and context
        assert self.args == [123, "str"]
        assert self.kwargs == {"variable": "test", "another": 1}
        footer_slot = self.slots["footer"]
        some_var = self.input.context["some_var"]

rendered = TestComponent.render(
    kwargs={"variable": "test", "another": 1},
    args=[123, "str"],
    slots={"footer": "MY_SLOT"},
)

args

args: Any

Positional arguments passed to the component.

This is part of the Render API.

args has the same behavior as the args argument of Component.get_template_data():

  • If you defined the Component.Args class, then the args property will return an instance of that Args class.
  • Otherwise, args will be a plain list.

Example

With Args class:

from django_components import Component

class Table(Component):
    class Args:
        page: int
        per_page: int

    def on_render_before(self, context: Context, template: Template | None) -> None:
        assert self.args.page == 123
        assert self.args.per_page == 10

rendered = Table.render(
    args=[123, 10],
)

Without Args class:

from django_components import Component

class Table(Component):
    def on_render_before(self, context: Context, template: Template | None) -> None:
        assert self.args[0] == 123
        assert self.args[1] == 10

raw_args

raw_args: list[Any]

Positional arguments passed to the component.

This is part of the Render API.

Unlike Component.args, this attribute is not typed and will remain as plain list even if you define the Component.Args class.

Example

from django_components import Component

class Table(Component):
    def on_render_before(self, context: Context, template: Template | None) -> None:
        assert self.raw_args[0] == 123
        assert self.raw_args[1] == 10

kwargs

kwargs: Any

Keyword arguments passed to the component.

This is part of the Render API.

kwargs has the same behavior as the kwargs argument of Component.get_template_data():

  • If you defined the Component.Kwargs class, then the kwargs property will return an instance of that Kwargs class.
  • Otherwise, kwargs will be a plain dict.

Kwargs have the defaults applied to them. Read more about Component defaults.

Example

With Kwargs class:

from django_components import Component

class Table(Component):
    class Kwargs:
        page: int
        per_page: int

    def on_render_before(self, context: Context, template: Template | None) -> None:
        assert self.kwargs.page == 123
        assert self.kwargs.per_page == 10

rendered = Table.render(
    kwargs={
        "page": 123,
        "per_page": 10,
    },
)

Without Kwargs class:

from django_components import Component

class Table(Component):
    def on_render_before(self, context: Context, template: Template | None) -> None:
        assert self.kwargs["page"] == 123
        assert self.kwargs["per_page"] == 10

raw_kwargs

raw_kwargs: dict[str, Any]

Keyword arguments passed to the component.

This is part of the Render API.

Unlike Component.kwargs, this attribute is not typed and will remain as plain dict even if you define the Component.Kwargs class.

raw_kwargs have the defaults applied to them. Read more about Component defaults.

Example

from django_components import Component

class Table(Component):
    def on_render_before(self, context: Context, template: Template | None) -> None:
        assert self.raw_kwargs["page"] == 123
        assert self.raw_kwargs["per_page"] == 10

slots

slots: Any

Slots passed to the component.

This is part of the Render API.

slots has the same behavior as the slots argument of Component.get_template_data():

  • If you defined the Component.Slots class, then the slots property will return an instance of that class.
  • Otherwise, slots will be a plain dict.

Example

With Slots class:

from django_components import Component, Slot, SlotInput

class Table(Component):
    class Slots:
        header: SlotInput
        footer: SlotInput

    def on_render_before(self, context: Context, template: Template | None) -> None:
        assert isinstance(self.slots.header, Slot)
        assert isinstance(self.slots.footer, Slot)

rendered = Table.render(
    slots={
        "header": "MY_HEADER",
        "footer": lambda ctx: "FOOTER: " + ctx.data["user_id"],
    },
)

Without Slots class:

from django_components import Component, Slot, SlotInput

class Table(Component):
    def on_render_before(self, context: Context, template: Template | None) -> None:
        assert isinstance(self.slots["header"], Slot)
        assert isinstance(self.slots["footer"], Slot)

raw_slots

raw_slots: dict[str, Slot]

Slots passed to the component.

This is part of the Render API.

Unlike Component.slots, this attribute is not typed and will remain as plain dict even if you define the Component.Slots class.

Example

from django_components import Component

class Table(Component):
    def on_render_before(self, context: Context, template: Template | None) -> None:
        assert self.raw_slots["header"] == "MY_HEADER"
        assert self.raw_slots["footer"] == "FOOTER: " + ctx.data["user_id"]

context

context: Context

The context argument as passed to Component.get_template_data().

This is Django's Context with which the component template is rendered.

If the root component or template was rendered with RequestContext then this will be an instance of RequestContext.

Whether the context variables defined in context are available to the template depends on the context behavior mode:

  • In "django" context behavior mode, the template will have access to the keys of this context.

  • In "isolated" context behavior mode, the template will NOT have access to this context, and data MUST be passed via component's args and kwargs.

deps_strategy

deps_strategy: DependenciesStrategy

Dependencies strategy defines how to handle JS and CSS dependencies of this and child components.

Read more about Dependencies rendering.

This is part of the Render API.

There are six strategies:

  • "document" (default)
    • Smartly inserts JS / CSS into placeholders or into <head> and <body> tags.
    • Requires the HTML to be rendered in a JS-enabled browser.
    • Inserts extra script for managing fragments.
  • "fragment"
    • A lightweight HTML fragment to be inserted into a document with AJAX.
    • Fragment will fetch its own JS / CSS dependencies when inserted into the page.
    • Requires the HTML to be rendered in a JS-enabled browser.
  • "simple"
    • Smartly insert JS / CSS into placeholders or into <head> and <body> tags.
    • No extra script loaded.
  • "prepend"
    • Insert JS / CSS before the rendered HTML.
    • No extra script loaded.
  • "append"
    • Insert JS / CSS after the rendered HTML.
    • No extra script loaded.
  • "ignore"
    • HTML is left as-is. You can still process it with a different strategy later with render_dependencies().
    • Used for inserting rendered HTML into other components.

outer_context

outer_context: Context | None

When a component is rendered with the {% component %} tag, this is the Django's Context object that was used just outside of the component.

{% with abc=123 %}
    {{ abc }} {# <--- This is in outer context #}
    {% component "my_component" / %}
{% endwith %}

This is relevant when your components are isolated, for example when using the "isolated" context behavior mode or when using the only flag.

When components are isolated, each component has its own instance of Context, so outer_context is different from the context argument.

registry

The ComponentRegistry instance that was used to render the component.

node

node: ComponentNode | None

The ComponentNode instance that was used to render the component.

This will be set only if the component was rendered with the {% component %} tag.

Accessing the ComponentNode is mostly useful for extensions, which can modify their behaviour based on the source of the Component.

class MyComponent(Component):
    def get_template_data(self, context, template):
        if self.node is not None:
            assert self.node.name == "my_component"

For example, if MyComponent was used in another component - that is, with a {% component "my_component" %} tag in a template that belongs to another component - then you can use self.node.template_component to access the owner Component class.

class Parent(Component):
    template: types.django_html = '''
        <div>
            {% component "my_component" / %}
        </div>
    '''

@register("my_component")
class MyComponent(Component):
    def get_template_data(self, context, template):
        if self.node is not None:
            assert self.node.template_component == Parent

Info

Component.node is None if the component is created by Component.render() (but you can pass in the node kwarg yourself).

is_filled

is_filled: SlotIsFilled

Deprecated. Will be removed in v1. Use Component.slots instead. Note that Component.slots no longer escapes the slot names.

Dictionary describing which slots have or have not been filled.

This attribute is available for use only within:

You can also access this variable from within the template as

{{ component_vars.is_filled.slot_name }}

request

request: HttpRequest | None

HTTPRequest object passed to this component.

Example

class MyComponent(Component):
    def get_template_data(self, args, kwargs, slots, context):
        user_id = self.request.GET['user_id']
        return {
            'user_id': user_id,
        }

Passing request to a component:

In regular Django templates, you have to use RequestContext to pass the HttpRequest object to the template.

With Components, you can either use RequestContext, or pass the request object explicitly via Component.render() and Component.render_to_response().

When a component is nested in another, the child component uses parent's request object.

context_processors_dataproperty

context_processors_data: dict

Retrieve data injected by context_processors.

This data is also available from within the component's template, without having to return this data from get_template_data().

In regular Django templates, you need to use RequestContext to apply context processors.

In Components, the context processors are applied to components either when:

  • The component is rendered with RequestContext (Regular Django behavior)
  • The component is rendered with a regular Context (or none), but the request kwarg of Component.render() is set.
  • The component is nested in another component that matches any of these conditions.

See Component.request on how the request (HTTPRequest) object is passed to and within the components.

NOTE: This dictionary is generated dynamically, so any changes to it will not be persisted.

Example

class MyComponent(Component):
    def get_template_data(self, args, kwargs, slots, context):
        user = self.context_processors_data['user']
        return {
            'is_logged_in': user.is_authenticated,
        }

parent

parent: Component | None

The parent component instance of the current component.

This is part of the Render API.

Returns the parent Component instance if this component is nested within another component, or None if this is the root component.

Example

class Theme(Component):
    ...

class Table(Component):
    def on_render_before(self, context, template):
        if self.parent is not None:
            # This component is nested in another component
            parent_type = type(self.parent).__name__
            ...

root

root: Component

The root component instance (top-most ancestor) of the current component.

This is part of the Render API.

Returns the root Component instance in the component tree. If this component is the root component, returns self.

Example

class Theme(Component):
    ...

class Table(Component):
    def get_template_data(self, args, kwargs, slots, context):
        # Access root component's data
        root_kwargs = self.root.kwargs
        ...

ancestorsproperty

ancestors: Generator[Component, None, None]

An iterator that yields all ancestor component instances, walking up the tree.

This is part of the Render API.

Yields Component instances starting from the parent component, then the parent's parent, and so on, up to (but not including) the root component.

Example

class Theme(Component):
    ...

class MarkdownEditor(Component):
    def get_template_data(self, args, kwargs, slots, context):
        # Check if this component is nested in a Theme component
        is_nested_in_theme = any(
            isinstance(comp, Theme) for comp in self.ancestors
        )
        if is_nested_in_theme:
            css_fix = "width: 200px; display: flex"
        else:
            css_fix = ""

        return {
            "css_fix": css_fix,
        }

Raises

  • RuntimeError – If accessed outside of component rendering context.

class_id

class_id: str

Unique ID of the component class, e.g. MyComponent_ab01f2.

This is derived from the component class' module import path, e.g. path.to.my.MyComponent.

do_not_call_in_templates

do_not_call_in_templates: bool

Django special property to prevent calling the instance as a function inside Django templates.

Read more about Django's do_not_call_in_templates.

Methods

get_template_name

get_template_name(context: Context) -> str | None

See source code

DEPRECATED: Use instead Component.template_file, Component.template or Component.on_render(). Will be removed in v1.

Same as Component.template_file, but allows to dynamically resolve the template name at render time.

See Component.template_file for more info and examples.

Warning

The context is not fully populated at the point when this method is called.

If you need to access the context, either use Component.on_render_before() or Component.on_render().

Warning

Only one of template_file, get_template_name(), template or get_template() must be defined.

ParameterTypeDescription
contextContextThe Django template Context in which the component is rendered.

Returns

  • str | None – str | None: The filepath to the template.

get_template

get_template(context: Context) -> str | Template | None

See source code

DEPRECATED: Use instead Component.template_file, Component.template or Component.on_render(). Will be removed in v1.

Same as Component.template, but allows to dynamically resolve the template at render time.

The template can be either plain string or a Template instance.

See Component.template for more info and examples.

Warning

Only one of template template_file, get_template_name(), or get_template() must be defined.

Warning

The context is not fully populated at the point when this method is called.

If you need to access the context, either use Component.on_render_before() or Component.on_render().

ParameterTypeDescription
contextContextThe Django template Context in which the component is rendered.

Returns

  • str | Template | None – str | Template | None: The inlined Django template string or a Template instance.

get_context_data

get_context_data(*_args: Any = (), **_kwargs: Any = {}) -> Mapping | None

See source code

DEPRECATED: Use get_template_data() instead. Will be removed in v2.

Use this method to define variables that will be available in the template.

Receives the args and kwargs as they were passed to the Component.

This method has access to the Render API.

Read more about Template variables.

Example

class MyComponent(Component):
    def get_context_data(self, name, *args, **kwargs):
        return {
            "name": name,
            "id": self.id,
        }

    template = "Hello, {{ name }}!"

MyComponent.render(name="World")

Warning

get_context_data() and get_template_data() are mutually exclusive.

If both methods return non-empty dictionaries, an error will be raised.

get_template_data

get_template_data(
    args: Any,
    kwargs: Any,
    slots: Any,
    context: Context
) -> Mapping | None

See source code

Use this method to define variables that will be available in the template.

This method has access to the Render API.

Read more about Template variables.

Example

class MyComponent(Component):
    def get_template_data(self, args, kwargs, slots, context):
        return {
            "name": kwargs["name"],
            "id": self.id,
        }

    template = "Hello, {{ name }}!"

MyComponent.render(name="World")
ParameterTypeDescription
argsAnyPositional arguments passed to the component.
kwargsAnyKeyword arguments passed to the component.
slotsAnySlots passed to the component.
context ([Context](https//docs.djangoproject.com/en/5.2/ref/templates/api/#django.template.Context)): Used for rendering the component template.

Pass-through kwargs:

It's best practice to explicitly define what args and kwargs a component accepts.

However, if you want a looser setup, you can easily write components that accept any number of kwargs, and pass them all to the template (similar to django-cotton).

To do that, simply return the kwargs dictionary itself from get_template_data():

class MyComponent(Component):
    def get_template_data(self, args, kwargs, slots, context):
        return kwargs

Type hints:

To get type hints for the args, kwargs, and slots parameters, you can define the Args, Kwargs, and Slots classes on the component class, and then directly reference them in the function signature of get_template_data().

When you set these classes, the args, kwargs, and slots parameters will be given as instances of these (args instance of Args, etc).

When you omit these classes, or set them to None, then the args, kwargs, and slots parameters will be given as plain lists / dictionaries, unmodified.

Read more on Typing and validation.

Example

from django.template import Context
from django_components import Component, SlotInput

class MyComponent(Component):
    class Args:
        color: str

    class Kwargs:
        size: int

    class Slots:
        footer: SlotInput

    def get_template_data(self, args: Args, kwargs: Kwargs, slots: Slots, context: Context):
        assert isinstance(args, MyComponent.Args)
        assert isinstance(kwargs, MyComponent.Kwargs)
        assert isinstance(slots, MyComponent.Slots)

        return {
            "color": args.color,
            "size": kwargs.size,
            "id": self.id,
        }

You can also add typing to the data returned from get_template_data() by defining the TemplateData class on the component class.

When you set this class, you can return either the data as a plain dictionary, or an instance of TemplateData.

If you return plain dictionary, the data will be validated against the TemplateData class by instantiating it with the dictionary.

Example

class MyComponent(Component):
    class TemplateData:
        color: str
        size: int

    def get_template_data(self, args, kwargs, slots, context):
        return {
            "color": kwargs["color"],
            "size": kwargs["size"],
        }
        # or
        return MyComponent.TemplateData(
            color=kwargs["color"],
            size=kwargs["size"],
        )

Warning

get_template_data() and get_context_data() are mutually exclusive.

If both methods return non-empty dictionaries, an error will be raised.

get_js_data

get_js_data(
    args: Any,
    kwargs: Any,
    slots: Any,
    context: Context
) -> Mapping | None

See source code

Use this method to define variables that will be available from within the component's JavaScript code.

This method has access to the Render API.

The data returned from this method will be serialized to JSON.

Read more about JavaScript variables.

Example

class MyComponent(Component):
    def get_js_data(self, args, kwargs, slots, context):
        return {
            "name": kwargs["name"],
            "id": self.id,
        }

    js = '''
        $onComponent(({ name, id }, ctx) => {
            console.log(name, id);
        });
    '''

MyComponent.render(name="World")
ParameterTypeDescription
argsAnyPositional arguments passed to the component.
kwargsAnyKeyword arguments passed to the component.
slotsAnySlots passed to the component.
context ([Context](https//docs.djangoproject.com/en/5.2/ref/templates/api/#django.template.Context)): Used for rendering the component template.

Pass-through kwargs:

It's best practice to explicitly define what args and kwargs a component accepts.

However, if you want a looser setup, you can easily write components that accept any number of kwargs, and pass them all to the JavaScript code.

To do that, simply return the kwargs dictionary itself from get_js_data():

class MyComponent(Component):
    def get_js_data(self, args, kwargs, slots, context):
        return kwargs

Type hints:

To get type hints for the args, kwargs, and slots parameters, you can define the Args, Kwargs, and Slots classes on the component class, and then directly reference them in the function signature of get_js_data().

When you set these classes, the args, kwargs, and slots parameters will be given as instances of these (args instance of Args, etc).

When you omit these classes, or set them to None, then the args, kwargs, and slots parameters will be given as plain lists / dictionaries, unmodified.

Read more on Typing and validation.

Example

from typing import NamedTuple
from django.template import Context
from django_components import Component, SlotInput

class MyComponent(Component):
    class Args:
        color: str

    class Kwargs:
        size: int

    class Slots:
        footer: SlotInput

    def get_js_data(self, args: Args, kwargs: Kwargs, slots: Slots, context: Context):
        assert isinstance(args, MyComponent.Args)
        assert isinstance(kwargs, MyComponent.Kwargs)
        assert isinstance(slots, MyComponent.Slots)

        return {
            "color": args.color,
            "size": kwargs.size,
            "id": self.id,
        }

You can also add typing to the data returned from get_js_data() by defining the JsData class on the component class.

When you set this class, you can return either the data as a plain dictionary, or an instance of JsData.

If you return plain dictionary, the data will be validated against the JsData class by instantiating it with the dictionary.

Example

class MyComponent(Component):
    class JsData:
        color: str
        size: int

    def get_js_data(self, args, kwargs, slots, context):
        return {
            "color": kwargs["color"],
            "size": kwargs["size"],
        }
        # or
        return MyComponent.JsData(
            color=kwargs["color"],
            size=kwargs["size"],
        )

get_css_data

get_css_data(
args: Any,
kwargs: Any,
slots: Any,
context: Context
) -> Mapping | None

See source code

Use this method to define variables that will be available from within the component's CSS code.

This method has access to the Render API.

The data returned from this method will be serialized to string.

Read more about CSS variables.

Example

class MyComponent(Component):
    def get_css_data(self, args, kwargs, slots, context):
        return {
            "color": kwargs["color"],
        }

    css = '''
        .my-class {
            color: var(--color);
        }
    '''

MyComponent.render(color="red")
ParameterTypeDescription
argsAnyPositional arguments passed to the component.
kwargsAnyKeyword arguments passed to the component.
slotsAnySlots passed to the component.
context ([Context](https//docs.djangoproject.com/en/5.2/ref/templates/api/#django.template.Context)): Used for rendering the component template.

Pass-through kwargs:

It's best practice to explicitly define what args and kwargs a component accepts.

However, if you want a looser setup, you can easily write components that accept any number of kwargs, and pass them all to the CSS code.

To do that, simply return the kwargs dictionary itself from get_css_data():

class MyComponent(Component):
    def get_css_data(self, args, kwargs, slots, context):
        return kwargs

Type hints:

To get type hints for the args, kwargs, and slots parameters, you can define the Args, Kwargs, and Slots classes on the component class, and then directly reference them in the function signature of get_css_data().

When you set these classes, the args, kwargs, and slots parameters will be given as instances of these (args instance of Args, etc).

When you omit these classes, or set them to None, then the args, kwargs, and slots parameters will be given as plain lists / dictionaries, unmodified.

Read more on Typing and validation.

Example

from django.template import Context
from django_components import Component, SlotInput

class MyComponent(Component):
    class Args:
        color: str

    class Kwargs:
        size: int

    class Slots:
        footer: SlotInput

    def get_css_data(self, args: Args, kwargs: Kwargs, slots: Slots, context: Context):
        assert isinstance(args, MyComponent.Args)
        assert isinstance(kwargs, MyComponent.Kwargs)
        assert isinstance(slots, MyComponent.Slots)

        return {
            "color": args.color,
            "size": kwargs.size,
        }

You can also add typing to the data returned from get_css_data() by defining the CssData class on the component class.

When you set this class, you can return either the data as a plain dictionary, or an instance of CssData.

If you return plain dictionary, the data will be validated against the CssData class by instantiating it with the dictionary.

Example

class MyComponent(Component):
    class CssData:
        color: str
        size: int

    def get_css_data(self, args, kwargs, slots, context):
        return {
            "color": kwargs["color"],
            "size": kwargs["size"],
        }
        # or
        return MyComponent.CssData(
            color=kwargs["color"],
            size=kwargs["size"],
        )

on_render_before

on_render_before(context: Context, template: Template | None) -> None

See source code

Runs just before the component's template is rendered.

It is called for every component, including nested ones, as part of the component render lifecycle.

ParameterTypeDescription
contextContextThe Django Context that will be used to render the component's template.
templateTemplate | NoneThe Django Template instance that will be rendered, or None if no template.

Returns

  • None – None. This hook is for side effects only.

Example

You can use this hook to access the context or the template:

from django.template import Context, Template
from django_components import Component

class MyTable(Component):
    def on_render_before(self, context: Context, template: Template | None) -> None:
        # Insert value into the Context
        context["from_on_before"] = ":)"

        assert isinstance(template, Template)

Warning

If you want to pass data to the template, prefer using get_template_data() instead of this hook.

Warning

Do NOT modify the template in this hook. The template is reused across renders.

Since this hook is called for every component, this means that the template would be modified every time a component is rendered.

on_render

on_render(context: Context, template: Template | None) -> SlotResult | OnRenderGenerator | None

See source code

This method does the actual rendering.

Read more about this hook in Component hooks.

You can override this method to:

  • Change what template gets rendered
  • Modify the context
  • Modify the rendered output after it has been rendered
  • Handle errors

The default implementation renders the component's Template with the given Context.

class MyTable(Component):
    def on_render(self, context, template):
        if template is None:
            return None
        else:
            return template.render(context)

The template argument is None if the component has no template.

Modifying rendered template

To change what gets rendered, you can:

  • Render a different template
  • Render a component
  • Return a different string or SafeString
class MyTable(Component):
    def on_render(self, context, template):
        return "Hello"

Post-processing rendered template

To access the final output, you can yield the result instead of returning it.

This will return a tuple of (rendered HTML, error). The error is None if the rendering succeeded.

class MyTable(Component):
    def on_render(self, context, template):
        html, error = yield lambda: template.render(context)

        if error is None:
            # The rendering succeeded
            return html
        else:
            # The rendering failed
            print(f"Error: {error}")

At this point you can do 3 things:

  1. Return a new HTML

    The new HTML will be used as the final output.

    If the original template raised an error, it will be ignored.

    class MyTable(Component):
        def on_render(self, context, template):
            html, error = yield lambda: template.render(context)
    
            return "NEW HTML"
    
  2. Raise a new exception

    The new exception is what will bubble up from the component.

    The original HTML and original error will be ignored.

    class MyTable(Component):
        def on_render(self, context, template):
            html, error = yield lambda: template.render(context)
    
            raise Exception("Error message")
    
  3. Return nothing (or None) to handle the result as usual

    If you don't raise an exception, and neither return a new HTML, then original HTML / error will be used:

    • If rendering succeeded, the original HTML will be used as the final output.
    • If rendering failed, the original error will be propagated.
    class MyTable(Component):
        def on_render(self, context, template):
            html, error = yield lambda: template.render(context)
    
            if error is not None:
                # The rendering failed
                print(f"Error: {error}")
    

Multiple yields

You can yield multiple times within the same on_render method. This is useful for complex rendering scenarios where you need to render different templates or handle multiple rendering operations:

class MyTable(Component):
    def on_render(self, context, template):
        # First yield - render with one context
        with context.push({"mode": "header"}):
            header_html, header_error = yield lambda: template.render(context)

        # Second yield - render with different context
        with context.push({"mode": "body"}):
            body_html, body_error = yield lambda: template.render(context)

        # Third yield - render a string directly
        footer_html, footer_error = yield "Footer content"

        # Process all results and return final output
        if header_error or body_error or footer_error:
            return "Error occurred during rendering"

        return f"{header_html}{body_html}{footer_html}"

Each yield operation is independent and returns its own (html, error) tuple, allowing you to handle each rendering result separately.

on_render_after

on_render_after(
    context: Context,
    template: Template | None,
    result: str | None,
    error: Exception | None
) -> SlotResult | None

See source code

Hook that runs when the component was fully rendered, including all its children.

It receives the same arguments as on_render_before(), plus the outcome of the rendering:

  • result: The rendered output of the component. None if the rendering failed.
  • error: The error that occurred during the rendering, or None if the rendering succeeded.

on_render_after() behaves the same way as the second part of on_render() (after the yield).

class MyTable(Component):
    def on_render_after(self, context, template, result, error):
        if error is None:
            # The rendering succeeded
            return result
        else:
            # The rendering failed
            print(f"Error: {error}")

Same as on_render(), you can return a new HTML, raise a new exception, or return nothing:

  1. Return a new HTML

    The new HTML will be used as the final output.

    If the original template raised an error, it will be ignored.

    class MyTable(Component):
        def on_render_after(self, context, template, result, error):
            return "NEW HTML"
    
  2. Raise a new exception

    The new exception is what will bubble up from the component.

    The original HTML and original error will be ignored.

    class MyTable(Component):
        def on_render_after(self, context, template, result, error):
            raise Exception("Error message")
    
  3. Return nothing (or None) to handle the result as usual

    If you don't raise an exception, and neither return a new HTML, then original HTML / error will be used:

    • If rendering succeeded, the original HTML will be used as the final output.
    • If rendering failed, the original error will be propagated.
    class MyTable(Component):
        def on_render_after(self, context, template, result, error):
            if error is not None:
                # The rendering failed
                print(f"Error: {error}")
    

on_dependenciesclassmethod

on_dependencies(scripts: list[Script], styles: list[Style]) -> tuple[list[Script], list[Style]] | None

See source code

Hook called once per rendered component instance with that component's Script/Style list.

The list includes Component.js/Component.css CSS/JS variables, and Component.Media.js/Component.Media.css.

Return (new_scripts, new_styles) to replace the list for this instance; return None (default) to keep the original list.

Example

class MyButton(Component):
    @classmethod
    def on_dependencies(cls, scripts, styles):
        # Add a nonce to every inline style for this component
        for style in styles:
            if style.content and "nonce" not in style.attrs:
                style.attrs["nonce"] = get_current_nonce()
        return (scripts, styles)

inject

inject(key: str, default: Any | None = None) -> Any

See source code

Use this method to retrieve the data that was passed to a {% provide %} tag with the corresponding key.

To retrieve the data, inject() must be called inside a component that's inside the {% provide %} tag.

You may also pass a default that will be used if the {% provide %} tag with given key was NOT found.

This method is part of the Render API, and raises an error if called from outside the rendering execution.

Read more about Provide / Inject.

Example

Given this template:

{% provide "my_provide" message="hello" %}
    {% component "my_comp" / %}
{% endprovide %}

And given this definition of "my_comp" component:

from django_components import Component, register

@register("my_comp")
class MyComp(Component):
    template = "hi {{ message }}!"

    def get_template_data(self, args, kwargs, slots, context):
        data = self.inject("my_provide")
        message = data.message
        return {"message": message}

This renders into:

hi hello!

As the {{ message }} is taken from the "my_provide" provider.

as_viewclassmethod

as_view(**initkwargs: Any = {}) -> ViewFn

See source code

Shortcut for calling Component.View.as_view and passing component instance to it.

Read more on Component views and URLs.

render_to_responseclassmethod

render_to_response(
    context: dict[str, Any] | Context | None = None,
    args: Any | None = None,
    kwargs: Any | None = None,
    slots: Any | None = None,
    deps_strategy: DependenciesStrategy | None = None,
    type: DependenciesStrategy | None = None,
    render_dependencies: bool = True,
    request: HttpRequest | None = None,
    outer_context: Context | None = None,
    registry: ComponentRegistry | None = None,
    registered_name: str | None = None,
    node: ComponentNode | None = None,
    **response_kwargs: Any = {}
) -> HttpResponse

See source code

Render the component and wrap the content in an HTTP response class.

render_to_response() takes the same inputs as Component.render(). See that method for more information.

After the component is rendered, the HTTP response class is instantiated with the rendered content.

Any additional kwargs are passed to the response class.

Example

Button.render_to_response(
    args=["John"],
    kwargs={
        "surname": "Doe",
        "age": 30,
    },
    slots={
        "footer": "i AM A SLOT",
    },
    # HttpResponse kwargs
    status=201,
    headers={...},
)
# HttpResponse(content=..., status=201, headers=...)

Custom response class:

You can set a custom response class on the component via Component.response_class. Defaults to django.http.HttpResponse.

from django.http import HttpResponse
from django_components import Component

class MyHttpResponse(HttpResponse):
    ...

class MyComponent(Component):
    response_class = MyHttpResponse

response = MyComponent.render_to_response()
assert isinstance(response, MyHttpResponse)

renderclassmethod

render(
context: dict[str, Any] | Context | None = None,
args: Any | None = None,
kwargs: Any | None = None,
slots: Any | None = None,
deps_strategy: DependenciesStrategy | None = None,
type: DependenciesStrategy | None = None,
render_dependencies: bool = True,
request: HttpRequest | None = None,
outer_context: Context | None = None,
registry: ComponentRegistry | None = None,
registered_name: str | None = None,
node: ComponentNode | None = None
) -> str

See source code

Render the component into a string. This is the equivalent of calling the {% component %} tag.

Button.render(
    args=["John"],
    kwargs={
        "surname": "Doe",
        "age": 30,
    },
    slots={
        "footer": "i AM A SLOT",
    },
)

Inputs:

  • args - Optional. A list of positional args for the component. This is the same as calling the component as:

    {% component "button" arg1 arg2 ... %}
    
  • kwargs - Optional. A dictionary of keyword arguments for the component. This is the same as calling the component as:

    {% component "button" key1=val1 key2=val2 ... %}
    
  • slots - Optional. A dictionary of slot fills. This is the same as passing {% fill %} tags to the component.

    {% component "button" %}
        {% fill "content" %}
            Click me!
        {% endfill %}
    {% endcomponent %}
    

    Dictionary keys are the slot names. Dictionary values are the slot fills.

    Slot fills can be strings, render functions, or Slot instances:

    Button.render(
        slots={
            "content": "Click me!"
            "content2": lambda ctx: "Click me!",
            "content3": Slot(lambda ctx: "Click me!"),
        },
    )
    
  • context - Optional. Plain dictionary or Django's Context. The context within which the component is rendered.

    When a component is rendered within a template with the {% component %} tag, this will be set to the Context instance that is used for rendering the template.

    When you call Component.render() directly from Python, you can ignore this input most of the time. Instead use args, kwargs, and slots to pass data to the component.

    You can pass RequestContext to the context argument, so that the component will gain access to the request object and will use context processors. Read more on Working with HTTP requests.

    Button.render(
        context=RequestContext(request),
    )
    

    For advanced use cases, you can use context argument to "pre-render" the component in Python, and then pass the rendered output as plain string to the template. With this, the inner component is rendered as if it was within the template with {% component %}.

    class Button(Component):
        def render(self, context, template):
            # Pass `context` to Icon component so it is rendered
            # as if nested within Button.
            # When nested, deps_strategy defaults to "ignore"
            icon = Icon.render(
                context=context,
                args=["icon-name"],
            )
            # Update context with icon
            with context.update({"icon": icon}):
                return template.render(context)
    

    Whether the variables defined in context are available to the template depends on the context behavior mode:

    • In "django" context behavior mode, the template will have access to the keys of this context.

    • In "isolated" context behavior mode, the template will NOT have access to this context, and data MUST be passed via component's args and kwargs.

  • deps_strategy - Optional. Configure how to handle JS and CSS dependencies. Read more about Dependencies rendering.

    There are six strategies:

    • "document" (default for top-level)
      • Smartly inserts JS / CSS into placeholders or into <head> and <body> tags.
      • Requires the HTML to be rendered in a JS-enabled browser.
      • Inserts extra script for managing fragments.
    • "fragment"
      • A lightweight HTML fragment to be inserted into a document with AJAX.
      • Fragment will fetch its own JS / CSS dependencies when inserted into the page.
      • Requires the HTML to be rendered in a JS-enabled browser.
    • "simple"
      • Smartly insert JS / CSS into placeholders or into <head> and <body> tags.
      • No extra script loaded.
    • "prepend"
      • Insert JS / CSS before the rendered HTML.
      • No extra script loaded.
    • "append"
      • Insert JS / CSS after the rendered HTML.
      • No extra script loaded.
    • "ignore" (default when nested)
      • HTML is left as-is. You can still process it with a different strategy later with render_dependencies().
      • Used for inserting rendered HTML into other components.
  • request - Optional. HTTPRequest object. Pass a request object directly to the component to apply context processors.

    Read more about Working with HTTP requests.

Behavior inside get_template_data():

When you pre-render a component in Python, and pass it into another component's get_template_data(), you should set deps_strategy="ignore" to avoid rendering the dependencies twice.

django-components makes this easier for you. When you call Component.render() from Python inside another component (e.g. in get_template_data()), deps_strategy defaults to "ignore" instead of "document".

class Outer(Component):
    def get_template_data(self, args, kwargs, slots, context):
        # defaults to "ignore" when nested
        content = Inner.render()
        return {"content": content}

# `deps_strategy` defaults to "document" when top-level
rendered = Outer.render()

Type hints:

Component.render() is NOT typed. To add type hints, you can wrap the inputs in component's Args, Kwargs, and Slots classes.

Read more on Typing and validation.

from django_components import Component, Slot, SlotInput

# Define the component with the types
class Button(Component):
    class Args:
        name: str

    class Kwargs:
        surname: str
        age: int

    class Slots:
        my_slot: SlotInput | None = None
        footer: SlotInput

# Add type hints to the render call
Button.render(
    args=Button.Args(
        name="John",
    ),
    kwargs=Button.Kwargs(
        surname="Doe",
        age=30,
    ),
    slots=Button.Slots(
        footer=Slot(lambda ctx: "Click me!"),
    ),
)

ComponentCache

ComponentCache(component: Component | None)

Bases: django_components.extension.ExtensionComponentConfig

See source code

The interface for Component.Cache.

The fields of this class are used to configure the component caching.

Read more about Component caching.

Example

from django_components import Component

class MyComponent(Component):
    class Cache:
        enabled = True
        ttl = 60 * 60 * 24  # 1 day
        cache_name = "my_cache"

Attributes

enabled

enabled: bool

Whether this Component should be cached. Defaults to False.

include_slots

include_slots: bool

Whether the slots should be hashed into the cache key.

If enabled, the following two cases will be treated as different entries:

{% component "mycomponent" name="foo" %}
    FILL ONE
{% endcomponent %}

{% component "mycomponent" name="foo" %}
    FILL TWO
{% endcomponent %}

Warning

Passing slots as functions to cached components with include_slots=True will raise an error.

Warning

Slot caching DOES NOT account for context variables within the {% fill %} tag.

For example, the following two cases will be treated as the same entry:

{% with my_var="foo" %}
    {% component "mycomponent" name="foo" %}
        {{ my_var }}
    {% endcomponent %}
{% endwith %}

{% with my_var="bar" %}
    {% component "mycomponent" name="bar" %}
        {{ my_var }}
    {% endcomponent %}
{% endwith %}

Currently it's impossible to capture used variables. This will be addressed in v2. Read more about it in https://github.com/django-components/django-components/issues/1164.

ttl

ttl: int | None

The time-to-live (TTL) in seconds, i.e. for how long should an entry be valid in the cache.

  • If > 0, the entries will be cached for the given number of seconds.
  • If -1, the entries will be cached indefinitely.
  • If 0, the entries won't be cached.
  • If None, the default TTL will be used.

cache_name

cache_name: str | None

The name of the cache to use. If None, the default cache will be used.

Methods

get_entry

get_entry(cache_key: str) -> Any

set_entry

set_entry(cache_key: str, value: Any) -> None

get_cache

get_cache() -> BaseCache

get_cache_key

get_cache_key(
args: list,
kwargs: dict,
slots: dict
) -> str

hash

hash(args: list, kwargs: dict) -> str

See source code

Defines how the input (both args and kwargs) is hashed into a cache key.

By default, hash() serializes the input into a string. As such, the default implementation might NOT be suitable if you need to hash complex objects.

hash_slots

hash_slots(slots: dict[str, Slot]) -> str

ComponentDebugHighlight

ComponentDebugHighlight(component: Component | None)

Bases: django_components.extension.ExtensionComponentConfig

See source code

The interface for Component.DebugHighlight.

The fields of this class are used to configure the component debug highlighting for this component and its direct slots.

Read more about Component debug highlighting.

Example

from django_components import Component

class MyComponent(Component):
    class DebugHighlight:
        highlight_components = True
        highlight_slots = True

To highlight ALL components and slots, set [extension defaults](../settings/#extensions_defaults) in your settings:

from django_components import ComponentsSettings

COMPONENTS = ComponentsSettings(
    extensions_defaults={
        "debug_highlight": {
            "highlight_components": True,
            "highlight_slots": True,
        },
    },
)

Attributes

highlight_components

Whether to highlight this component in the rendered output.

highlight_slots

Whether to highlight slots of this component in the rendered output.

ComponentDefaults

ComponentDefaults(component: Component | None)

Bases: django_components.extension.ExtensionComponentConfig

See source code

The interface for Component.Defaults.

The fields of this class are used to set default values for the component's kwargs.

Read more about Component defaults.

Example

from django_components import Component, Default

class MyComponent(Component):
    class Defaults:
        position = "left"
        selected_items = Default(lambda: [1, 2, 3])

ComponentExtension

ComponentExtension()

Bases: object

See source code

Base class for all extensions.

Read more on Extensions.

Example

class ExampleExtension(ComponentExtension):
    name = "example"

    # Component-level behavior and settings. User will be able to override
    # the attributes and methods defined here on the component classes.
    class ComponentConfig(ComponentExtension.ComponentConfig):
        foo = "1"
        bar = "2"

        def baz(cls):
            return "3"

    # URLs
    urls = [
        URLRoute(path="dummy-view/", handler=dummy_view, name="dummy"),
        URLRoute(path="dummy-view-2/<int:id>/<str:name>/", handler=dummy_view_2, name="dummy-2"),
    ]

    # Commands
    commands = [
        HelloWorldCommand,
    ]

    # Hooks
    def on_component_class_created(self, ctx: OnComponentClassCreatedContext) -> None:
        print(ctx.component_cls.__name__)

    def on_component_class_deleted(self, ctx: OnComponentClassDeletedContext) -> None:
        print(ctx.component_cls.__name__)

Which users then can override on a per-component basis. E.g.:

class MyComp(Component):
    class Example:
        foo = "overridden"

        def baz(self):
            return "overridden baz"

Attributes

name

name: str

Name of the extension.

Name must be lowercase, and must be a valid Python identifier (e.g. "my_extension").

The extension may add new features to the Component class by allowing users to define and access a nested class in the Component class.

The extension name determines the name of the nested class in the Component class, and the attribute under which the extension will be accessible.

E.g. if the extension name is "my_extension", then the nested class in the Component class will be MyExtension, and the extension will be accessible as MyComp.my_extension.

class MyComp(Component):
    class MyExtension:
        ...

    def get_template_data(self, args, kwargs, slots, context):
        return {
            "my_extension": self.my_extension.do_something(),
        }

Info

The extension class name can be customized by setting the class_name attribute.

class_name

class_name: str

Name of the extension class.

By default, this is set automatically at class creation. The class name is the same as the name attribute, but with snake_case converted to PascalCase.

So if the extension name is "my_extension", then the extension class name will be "MyExtension".

class MyComp(Component):
    class MyExtension:  # <--- This is the extension class
        ...

To customize the class name, you can manually set the class_name attribute.

The class name must be a valid Python identifier.

Example

class MyExt(ComponentExtension):
    name = "my_extension"
    class_name = "MyCustomExtension"

This will make the extension class name "MyCustomExtension".

class MyComp(Component):
    class MyCustomExtension:  # <--- This is the extension class
        ...

ComponentConfig

ComponentConfig: type[ExtensionComponentConfig]

Base class that the "component-level" extension config nested within a Component class will inherit from.

This is where you can define new methods and attributes that will be available to the component instance.

Background:

The extension may add new features to the Component class by allowing users to define and access a nested class in the Component class. E.g.:

class MyComp(Component):
    class MyExtension:
        ...

    def get_template_data(self, args, kwargs, slots, context):
        return {
            "my_extension": self.my_extension.do_something(),
        }

When rendering a component, the nested extension class will be set as a subclass of ComponentConfig. So it will be same as if the user had directly inherited from extension's ComponentConfig. E.g.:

class MyComp(Component):
    class MyExtension(ComponentExtension.ComponentConfig):
        ...

This setting decides what the extension class will inherit from.

commands

List of commands that can be run by the extension.

These commands will be available to the user as components ext run <extension> <command>.

Commands are defined as subclasses of ComponentCommand.

Example

This example defines an extension with a command that prints "Hello world". To run the command, the user would run components ext run hello_world hello.

from django_components import ComponentCommand, ComponentExtension, CommandArg, CommandArgGroup

class HelloWorldCommand(ComponentCommand):
    name = "hello"
    help = "Hello world command."

    # Allow to pass flags `--foo`, `--bar` and `--baz`.
    # Argument parsing is managed by `argparse`.
    arguments = [
        CommandArg(
            name_or_flags="--foo",
            help="Foo description.",
        ),
        # When printing the command help message, `bar` and `baz`
        # will be grouped under "group bar".
        CommandArgGroup(
            title="group bar",
            description="Group description.",
            arguments=[
                CommandArg(
                    name_or_flags="--bar",
                    help="Bar description.",
                ),
                CommandArg(
                    name_or_flags="--baz",
                    help="Baz description.",
                ),
            ],
        ),
    ]

    # Callback that receives the parsed arguments and options.
    def handle(self, *args, **kwargs):
        print(f"HelloWorldCommand.handle: args={args}, kwargs={kwargs}")

# Associate the command with the extension
class HelloWorldExtension(ComponentExtension):
    name = "hello_world"

    commands = [
        HelloWorldCommand,
    ]

Methods

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"

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"

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)

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"

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)

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}'")

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}'")

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.

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"

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}")

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")

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}")

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")

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")

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}")

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)

ComponentFileEntry

ComponentFileEntry()

Bases: tuple

See source code

Result returned by get_component_files().

Attributes

dot_path

dot_path: str

The python import path for the module. E.g. app.components.mycomp

filepath

filepath: Path

The filesystem path to the module. E.g. /path/to/project/app/components/mycomp.py

ComponentInput

ComponentInput(
    context: Context,
    args: list,
    kwargs: dict,
    slots: dict[SlotName, Slot],
    deps_strategy: DependenciesStrategy,
    type: DependenciesStrategy,
    render_dependencies: bool
)

Bases: object

See source code

Deprecated. Will be removed in v1.

Object holding the inputs that were passed to Component.render() or the {% component %} template tag.

This object is available only during render under Component.input.

Read more about the Render API.

Attributes

context

context: Context

Django's Context passed to Component.render()

args

args: list

Positional arguments (as list) passed to Component.render()

kwargs

kwargs: dict

Keyword arguments (as dict) passed to Component.render()

slots

slots: dict[SlotName, Slot]

Slots (as dict) passed to Component.render()

deps_strategy

deps_strategy: DependenciesStrategy

Dependencies strategy passed to Component.render()

type

Deprecated. Will be removed in v1. Use deps_strategy instead.

render_dependencies

render_dependencies: bool

Deprecated. Will be removed in v1. Use deps_strategy="ignore" instead.

ComponentMediaInput

ComponentMediaInput()

Bases: typing.Protocol

See source code

Defines JS and CSS media files associated with a Component.

class MyTable(Component):
    class Media:
        js = [
            "path/to/script.js",
            "https://unpkg.com/alpinejs@3.14.7/dist/cdn.min.js",  # AlpineJS
        ]
        css = {
            "all": [
                "path/to/style.css",
                "https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css",  # TailwindCSS
            ],
            "print": ["path/to/style2.css"],
        }

Attributes

css

CSS files associated with a Component.

  • If a string, it's assumed to be a path to a CSS file.

  • If a list, each entry is assumed to be a path to a CSS file.

  • If a dict, the keys are media types (e.g. "all", "print", "screen", etc.), and the values are either:

    • A string, assumed to be a path to a CSS file.
    • A list, each entry is assumed to be a path to a CSS file.

Each entry can be a string, bytes, SafeString, PathLike, or a callable that returns one of the former (see ComponentMediaInputPath).

Example

class MyComponent(Component):
    class Media:
        css = "path/to/style.css"
class MyComponent(Component):
    class Media:
        css = ["path/to/style1.css", "path/to/style2.css"]
class MyComponent(Component):
    class Media:
        css = {
            "all": "path/to/style.css",
            "print": "path/to/print.css",
        }
class MyComponent(Component):
    class Media:
        css = {
            "all": ["path/to/style1.css", "path/to/style2.css"],
            "print": "path/to/print.css",
        }

js

JS files associated with a Component.

  • If a string, it's assumed to be a path to a JS file.

  • If a list, each entry is assumed to be a path to a JS file.

Each entry can be a string, bytes, SafeString, PathLike, or a callable that returns one of the former (see ComponentMediaInputPath).

Example

class MyComponent(Component):
    class Media:
        js = "path/to/script.js"
class MyComponent(Component):
    class Media:
        js = ["path/to/script1.js", "path/to/script2.js"]
class MyComponent(Component):
    class Media:
        js = lambda: ["path/to/script1.js", "path/to/script2.js"]

extend

extend: bool | list[type[Component]]

Configures whether the component should inherit the media files from the parent component.

  • If True, the component inherits the media files from the parent component.
  • If False, the component does not inherit the media files from the parent component.
  • If a list of components classes, the component inherits the media files ONLY from these specified components.

Read more in Media inheritance section.

Example

Disable media inheritance:

class ParentComponent(Component):
    class Media:
        js = ["parent.js"]

class MyComponent(ParentComponent):
    class Media:
        extend = False  # Don't inherit parent media
        js = ["script.js"]

print(MyComponent.media._js)  # ["script.js"]

Specify which components to inherit from. In this case, the media files are inherited ONLY from the specified components, and NOT from the original parent components:

class ParentComponent(Component):
    class Media:
        js = ["parent.js"]

class MyComponent(ParentComponent):
    class Media:
        # Only inherit from these, ignoring the files from the parent
        extend = [OtherComponent1, OtherComponent2]

        js = ["script.js"]

print(MyComponent.media._js)  # ["script.js", "other1.js", "other2.js"]

ComponentMediaInputPath

ComponentMediaInputPath: TypeAlias

See source code

A type representing an entry in Media.js or Media.css.

If an entry is a SafeString, a Script, a Style, or any object with __html__ method, it is treated as a pre-rendered tag and output as-is. Otherwise, it's assumed to be a path to a file.

Example

from django_components import Script, Style

class MyComponent(Component):
    class Media:
        js = [
            "path/to/script.js",
            b"script.js",
            SafeString("<script src='path/to/script.js'></script>"),
            Script(content="console.log('inline');"),
            Script(url="/static/analytics.js", content=None),
        ]
        css = [
            Path("path/to/style.css"),
            lambda: "path/to/style.css",
            lambda: Path("path/to/style.css"),
            Style(content=".x { color: red; }"),
            Style(url="/static/print.css", content=None, attrs={"media": "print"}),
        ]

ComponentNode

ComponentNode(
    name: str,
    registry: ComponentRegistry,
    params: list[TagAttr],
    filters: dict[str, Callable[[Any, Any], Any]],
    tags: dict[str, Callable[[Any, Any], Any]],
    flags: dict[str, bool] | None = None,
    nodelist: NodeList | None = None,
    node_id: str | None = None,
    contents: str | None = None,
    template_name: str | None = None,
    template_component: type[Component] | None = None,
    start_tag_source: str | None = None
)

Bases: django_components.node.BaseNode

See source code

Renders one of the components that was previously registered with @register() decorator.

The {% component %} tag takes:

  • Component's registered name as the first positional argument,
  • Followed by any number of positional and keyword arguments.
{% load component_tags %}
<div>
    {% component "button" name="John" job="Developer" / %}
</div>

The component name must be a string literal.

Inserting slot fills

If the component defined any slots, you can "fill" these slots by placing the {% fill %} tags within the {% component %} tag:

{% component "my_table" rows=rows headers=headers %}
  {% fill "pagination" %}
    < 1 | 2 | 3 >
  {% endfill %}
{% endcomponent %}

You can even nest {% fill %} tags within {% if %}, {% for %} and other tags:

{% component "my_table" rows=rows headers=headers %}
    {% if rows %}
        {% fill "pagination" %}
            < 1 | 2 | 3 >
        {% endfill %}
    {% endif %}
{% endcomponent %}

Isolating components

By default, components behave similarly to Django's {% include %}, and the template inside the component has access to the variables defined in the outer template.

You can selectively isolate a component, using the only flag, so that the inner template can access only the data that was explicitly passed to it:

{% component "name" positional_arg keyword_arg=value ... only %}

Alternatively, you can set all components to be isolated by default, by setting context_behavior to "isolated" in your settings:

# settings.py
COMPONENTS = {
    "context_behavior": "isolated",
}

Omitting the component keyword

If you would like to omit the component keyword, and simply refer to your components by their registered names:

{% button name="John" job="Developer" / %}

You can do so by setting the "shorthand" Tag formatter in the settings:

# settings.py
COMPONENTS = {
    "tag_formatter": "django_components.component_shorthand_formatter",
}

Attributes

Methods

parseclassmethod

parse(
    parser: Parser,
    token: Token,
    registry: ComponentRegistry,
    name: str,
    start_tag: str,
    end_tag: str
) -> ComponentNode

render

render(
context: Context,
*args: Any = (),
**kwargs: Any = {}
) -> str

ComponentRegistry

ComponentRegistry(library: Library | None = None, settings: RegistrySettings | Callable[[ComponentRegistry], RegistrySettings] | None = None)

Bases: object

See source code

Manages components and makes them available in the template, by default as {% component %} tags.

{% component "my_comp" key=value %}
{% endcomponent %}

To enable a component to be used in a template, the component must be registered with a component registry.

When you register a component to a registry, behind the scenes the registry automatically adds the component's template tag (e.g. {% component %} to the Library. And the opposite happens when you unregister a component - the tag is removed.

See Registering components.

ParameterTypeDescription
libraryLibrary | NoneDjango Library associated with this registry. If omitted, the default Library instance from django_components is used. (default: None)
settingsRegistrySettings | Callable[[ComponentRegistry], RegistrySettings] | NoneConfigure how the components registered with this registry will behave when rendered. See RegistrySettings. Can be either a static value or a callable that returns the settings. If omitted, the settings from COMPONENTS are used. (default: None)

Notes:

Example

# Use with default Library
registry = ComponentRegistry()

# Or a custom one
my_lib = Library()
registry = ComponentRegistry(library=my_lib)

# Usage
registry.register("button", ButtonComponent)
registry.register("card", CardComponent)
registry.all()
registry.clear()
registry.get("button")
registry.has("button")

Using registry to share components

You can use component registry for isolating or "packaging" components:

  1. Create new instance of ComponentRegistry and Library:

    my_comps = Library()
    my_comps_reg = ComponentRegistry(library=my_comps)
    
  2. Register components to the registry:

    my_comps_reg.register("my_button", ButtonComponent)
    my_comps_reg.register("my_card", CardComponent)
    
  3. In your target project, load the Library associated with the registry:

    {% load my_comps %}
    
  4. Use the registered components in your templates:

    {% component "button" %}
    {% endcomponent %}
    

Attributes

libraryproperty

library: Library

The template tag Library that is associated with the registry.

settingsproperty

settings: InternalRegistrySettings

Registry settings configured for this registry.

Methods

register

register(name: str, component: type[Component]) -> None

See source code

Register a Component class with this registry under the given name.

A component MUST be registered before it can be used in a template such as:

{% component "my_comp" %}
{% endcomponent %}

register() is additive. Calling it again with the exact same class object is a no-op. Calling it with any other class - even one whose class_id collides with the existing one - raises AlreadyRegistered. Call unregister() first if you intend to replace the registered class.

ParameterTypeDescription
namestrThe name under which the component will be registered. Required.
componenttype[Component]The component class to register. Required.

Raises

  • AlreadyRegistered – if name is already registered with any class other than component itself.

Example

registry.register("button", ButtonComponent)

unregister

unregister(name: str) -> None

See source code

Unregister the Component class that was registered under the given name.

Once a component is unregistered, it is no longer available in the templates.

ParameterTypeDescription
namestrThe name under which the component is registered. Required.

Raises

Example

# First register component
registry.register("button", ButtonComponent)
# Then unregister
registry.unregister("button")

get

get(name: str) -> type[Component]

See source code

Retrieve a Component class registered under the given name.

ParameterTypeDescription
namestrThe name under which the component was registered. Required.

Returns

  • type[Component] – type[Component]: The component class registered under the given name.

Raises

Example

# First register component
registry.register("button", ButtonComponent)
# Then get
registry.get("button")
# > ButtonComponent

has

has(name: str) -> bool

See source code

Check if a Component class is registered under the given name.

ParameterTypeDescription
namestrThe name under which the component was registered. Required.

Returns

  • boolTrue if the component is registered, False otherwise.

Example

# First register component
registry.register("button", ButtonComponent)
# Then check
registry.has("button")
# > True

all

all() -> dict[str, type[Component]]

See source code

Retrieve all registered Component classes.

Returns

  • dict[str, type[Component]] – dict[str, type[Component]]: A dictionary of component names to component classes

Example

# First register components
registry.register("button", ButtonComponent)
registry.register("card", CardComponent)
# Then get all
registry.all()
# > {
# >   "button": ButtonComponent,
# >   "card": CardComponent,
# > }

clear

clear() -> None

See source code

Clears the registry, unregistering all components.

Example

# First register components
registry.register("button", ButtonComponent)
registry.register("card", CardComponent)
# Then clear
registry.clear()
# Then get all
registry.all()
# > {}

ComponentVars

ComponentVars()

Bases: tuple

See source code

Type for the variables available inside the component templates.

All variables here are scoped under component_vars., so e.g. attribute kwargs on this class is accessible inside the template as:

{{ component_vars.kwargs }}

Attributes

args

args: Any

The args argument as passed to Component.get_template_data().

This is the same Component.args that's available on the component instance.

If you defined the Component.Args class, then the args property will return an instance of that class.

Otherwise, args will be a plain list.

Example

With Args class:

from django_components import Component, register

@register("table")
class Table(Component):
    class Args:
        page: int
        per_page: int

    template = '''
        <div>
            <h1>Table</h1>
            <p>Page: {{ component_vars.args.page }}</p>
            <p>Per page: {{ component_vars.args.per_page }}</p>
        </div>
    '''

Without Args class:

from django_components import Component, register

@register("table")
class Table(Component):
    template = '''
        <div>
            <h1>Table</h1>
            <p>Page: {{ component_vars.args.0 }}</p>
            <p>Per page: {{ component_vars.args.1 }}</p>
        </div>
    '''

kwargs

kwargs: Any

The kwargs argument as passed to Component.get_template_data().

This is the same Component.kwargs that's available on the component instance.

If you defined the Component.Kwargs class, then the kwargs property will return an instance of that class.

Otherwise, kwargs will be a plain dict.

Example

With Kwargs class:

from django_components import Component, register

@register("table")
class Table(Component):
    class Kwargs:
        page: int
        per_page: int

    template = '''
        <div>
            <h1>Table</h1>
            <p>Page: {{ component_vars.kwargs.page }}</p>
            <p>Per page: {{ component_vars.kwargs.per_page }}</p>
        </div>
    '''

Without Kwargs class:

from django_components import Component, register

@register("table")
class Table(Component):
    template = '''
        <div>
            <h1>Table</h1>
            <p>Page: {{ component_vars.kwargs.page }}</p>
            <p>Per page: {{ component_vars.kwargs.per_page }}</p>
        </div>
    '''

slots

slots: Any

The slots argument as passed to Component.get_template_data().

This is the same Component.slots that's available on the component instance.

If you defined the Component.Slots class, then the slots property will return an instance of that class.

Otherwise, slots will be a plain dict.

Example

With Slots class:

from django_components import Component, SlotInput, register

@register("table")
class Table(Component):
    class Slots:
        footer: SlotInput

    template = '''
        <div>
            {% component "pagination" %}
                {% fill "footer" body=component_vars.slots.footer / %}
            {% endcomponent %}
        </div>
    '''

Without Slots class:

from django_components import Component, SlotInput, register

@register("table")
class Table(Component):
    template = '''
        <div>
            {% component "pagination" %}
                {% fill "footer" body=component_vars.slots.footer / %}
            {% endcomponent %}
        </div>
    '''

is_filled

is_filled: dict[str, bool]

Deprecated. Will be removed in v1. Use component_vars.slots instead. Note that component_vars.slots no longer escapes the slot names.

Dictonary describing which component slots are filled (True) or are not (False).

New in version 0.70

Use as {{ component_vars.is_filled }}

Example

{# Render wrapping HTML only if the slot is defined #}
{% if component_vars.is_filled.my_slot %}
    <div class="slot-wrapper">
        {% slot "my_slot" / %}
    </div>
{% endif %}

This is equivalent to checking if a given key is among the slot fills:

class MyTable(Component):
    def get_template_data(self, args, kwargs, slots, context):
        return {
            "my_slot_filled": "my_slot" in slots
        }

ComponentView

ComponentView(component: Component, **kwargs: Any = {})

Bases: django_components.extension.ExtensionComponentConfig, django.views.generic.base.View

See source code

The interface for Component.View.

The fields of this class are used to configure the component views and URLs.

This class is a subclass of django.views.View.

Override the methods of this class to define the behavior of the component.

Read more about Component views and URLs.

The Component class is available via self.component_cls.

Example

Define a handler that runs for GET HTTP requests:

class MyComponent(Component):
    class View:
        def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
            return HttpResponse("Hello, world!")

Component URL:

Use get_component_url() to retrieve the component URL - an anonymous HTTP endpoint that triggers the component's handlers without having to register the component in urlpatterns.

A component is automatically exposed when you define at least one HTTP handler. To explicitly expose/hide the component, use Component.View.public = True.

from django_components import Component, get_component_url

class MyComponent(Component):
    class View:
        def get(self, request, *args, **kwargs):
            return HttpResponse("Hello, world!")

url = get_component_url(MyComponent)

This will create a URL route like /components/ext/view/components/a1b2c3/.

The component URL route can be customized by overriding get_route_path().

Attributes

component

DEPRECATED: Will be removed in v1.0. Use component_cls instead.

This is a dummy instance created solely for the View methods.

It is the same as if you instantiated the component class directly:

component = Calendar()
component.render_to_response(request=request)

component_cls

The parent component class.

Example

class MyComponent(Component):
    class View:
        def get(self, request):
            return self.component_cls.render_to_response(request=request)

urlproperty

url: str

The URL for the component.

Raises RuntimeError if the component is not public. See Component.View.public.

This is the same as calling get_component_url() with the current Component class:

class MyComponent(Component):
    class View:
        def get(self, request):
            component_url = get_component_url(self.component_cls)
            assert self.url == component_url

public

public: bool | None

Whether the component HTTP handlers should be available via a URL.

By default (None), the component HTTP handlers are available via a URL if any of the HTTP methods are defined.

You can explicitly set public to True or False to override this behaviour.

Example

Define the component HTTP handlers and get its URL using [get_component_url()](#get_component_url):

from django_components import Component, get_component_url

class MyComponent(Component):
    class View:
        def get(self, request):
            return self.component_cls.render_to_response(request=request)

url = get_component_url(MyComponent)

This will create a URL route like /components/ext/view/components/a1b2c3/.

To explicitly hide the component, set public = False:

class MyComponent(Component):
    class View:
        public = False

        def get(self, request):
            return self.component_cls.render_to_response(request=request)

Methods

get_route_pathclassmethod

get_route_path() -> str

See source code

Get the route path for the component.

By default, this is components/{component.class_id}/.

You can override this method to customize the route path.

Example

from django_components import Component, get_component_url

class MyComponent(Component):
    class View:
        @classmethod
        def get_route_path(cls):
            return f"my/custom/path/{cls.component_cls.class_id}/<int:pk>/"

# Get the URL with route parameters filled
url = get_component_url(MyComponent, kwargs={"pk": 123})
# /components/ext/view/my/custom/path/c1ab2c3/123/

get

get(
request: HttpRequest,
*args: Any = (),
**kwargs: Any = {}
) -> HttpResponse

post

post(
request: HttpRequest,
*args: Any = (),
**kwargs: Any = {}
) -> HttpResponse

put

put(
request: HttpRequest,
*args: Any = (),
**kwargs: Any = {}
) -> HttpResponse

patch

patch(
request: HttpRequest,
*args: Any = (),
**kwargs: Any = {}
) -> HttpResponse

delete

delete(
request: HttpRequest,
*args: Any = (),
**kwargs: Any = {}
) -> HttpResponse

head

head(
request: HttpRequest,
*args: Any = (),
**kwargs: Any = {}
) -> HttpResponse

options

options(
request: HttpRequest,
*args: Any = (),
**kwargs: Any = {}
) -> HttpResponse

trace

trace(
request: HttpRequest,
*args: Any = (),
**kwargs: Any = {}
) -> HttpResponse

ComponentsSettings

ComponentsSettings()

Bases: tuple

See source code

Settings available for django_components.

Example

COMPONENTS = ComponentsSettings(
    autodiscover=False,
    dirs = [BASE_DIR / "components"],
)

Attributes

extensions

extensions: Sequence[type[ComponentExtension] | str] | None

List of extensions to be loaded.

The extensions can be specified as:

  • Python import path, e.g. "path.to.my_extension.MyExtension".
  • Extension class, e.g. my_extension.MyExtension.

Read more about extensions.

Example

COMPONENTS = ComponentsSettings(
    extensions=[
        "path.to.my_extension.MyExtension",
        StorybookExtension,
    ],
)

extensions_defaults

extensions_defaults: dict[str, Any] | None

Global defaults for the extension classes.

Read more about Extension defaults.

Example

COMPONENTS = ComponentsSettings(
    extensions_defaults={
        "my_extension": {
            "my_setting": "my_value",
        },
        "cache": {
            "enabled": True,
            "ttl": 60,
        },
    },
)

autodiscover

autodiscover: bool | None

Toggle whether to run autodiscovery at the Django server startup.

Defaults to True

COMPONENTS = ComponentsSettings(
    autodiscover=False,
)

dirs

dirs: Sequence[str | PathLike | tuple[str, str] | tuple[str, PathLike]] | None

Specify the directories that contain your components.

Defaults to [Path(settings.BASE_DIR) / "components"]. That is, the root components/ app.

Directories must be full paths, same as with STATICFILES_DIRS.

These locations are searched during autodiscovery, or when you define HTML, JS, or CSS as separate files.

COMPONENTS = ComponentsSettings(
    dirs=[BASE_DIR / "components"],
)

Set to empty list to disable global components directories:

COMPONENTS = ComponentsSettings(
    dirs=[],
)

app_dirs

app_dirs: Sequence[str] | None

Specify the app-level directories that contain your components.

Defaults to ["components"]. That is, for each Django app, we search <app>/components/ for components.

The paths must be relative to app, e.g.:

COMPONENTS = ComponentsSettings(
    app_dirs=["my_comps"],
)

To search for <app>/my_comps/.

These locations are searched during autodiscovery, or when you define HTML, JS, or CSS as separate files.

Set to empty list to disable app-level components:

COMPONENTS = ComponentsSettings(
    app_dirs=[],
)

cache

cache: str | None

Name of the Django cache to be used for storing component's JS and CSS files.

If None, a LocMemCache is used with default settings.

Defaults to None.

Read more about caching.

COMPONENTS = ComponentsSettings(
    cache="my_cache",
)

context_behavior

context_behavior: ContextBehaviorType | None

Configure whether, inside a component template, you can use variables from the outside ("django") or not ("isolated"). This also affects what variables are available inside the {% fill %} tags.

Also see Component context and scope.

Defaults to "django".

COMPONENTS = ComponentsSettings(
    context_behavior="isolated",
)

NOTE: context_behavior and slot_context_behavior options were merged in v0.70.

If you are migrating from BEFORE v0.67, set context_behavior to "django". From v0.67 to v0.78 (incl) the default value was "isolated".

For v0.79 and later, the default is again "django". See the rationale for this change.

debug_highlight_components

debug_highlight_components: bool | None

DEPRECATED. Use extensions_defaults instead. Will be removed in v1.

Enable / disable component highlighting. See Troubleshooting for more details.

Defaults to False.

COMPONENTS = ComponentsSettings(
    debug_highlight_components=True,
)

debug_highlight_slots

debug_highlight_slots: bool | None

DEPRECATED. Use extensions_defaults instead. Will be removed in v1.

Enable / disable slot highlighting. See Troubleshooting for more details.

Defaults to False.

COMPONENTS = ComponentsSettings(
    debug_highlight_slots=True,
)

dynamic_component_name

dynamic_component_name: str | None

By default, the dynamic component is registered under the name "dynamic".

In case of a conflict, you can use this setting to change the component name used for the dynamic components.

# settings.py
COMPONENTS = ComponentsSettings(
    dynamic_component_name="my_dynamic",
)

After which you will be able to use the dynamic component with the new name:

{% component "my_dynamic" is=table_comp data=table_data headers=table_headers %}
    {% fill "pagination" %}
        {% component "pagination" / %}
    {% endfill %}
{% endcomponent %}

libraries

libraries: list[str] | None

Configure extra python modules that should be loaded.

This may be useful if you are not using the autodiscovery feature, or you need to load components from non-standard locations. Thus you can have a structure of components that is independent from your apps.

Expects a list of python module paths. Defaults to empty list.

Example

COMPONENTS = ComponentsSettings(
    libraries=[
        "mysite.components.forms",
        "mysite.components.buttons",
        "mysite.components.cards",
    ],
)

This would be the equivalent of importing these modules from within Django's AppConfig.ready():

class MyAppConfig(AppConfig):
    def ready(self):
        import "mysite.components.forms"
        import "mysite.components.buttons"
        import "mysite.components.cards"
Manually loading libraries

In the rare case that you need to manually trigger the import of libraries, you can use the import_libraries() function:

from django_components import import_libraries

import_libraries()

multiline_tags

multiline_tags: bool | None

Enable / disable multiline support for template tags. If True, template tags like {% component %} or {{ my_var }} can span multiple lines.

Defaults to True.

Disable this setting if you are making custom modifications to Django's regular expression for parsing templates at django.template.base.tag_re.

COMPONENTS = ComponentsSettings(
    multiline_tags=False,
)

reload_on_template_change

reload_on_template_change: bool | None

Deprecated. Use COMPONENTS.reload_on_file_change instead.

reload_on_file_change

reload_on_file_change: bool | ReloadModeType | None

Configure how django_components reacts when component files (HTML templates, JS, CSS) change on disk while the dev server is running.

See Hot-reloading component files during development.

Options:

  • False or "off" - No file watching. Changes are not picked up until the server is manually restarted.
  • True or "hot" - Clear the in-memory component cache so the next render reads fresh content from disk. The dev server keeps running without a restart.
  • "restart" - Same as "hot", but also triggers a full dev server restart. Deprecated, will be removed in v1.

Defaults to "hot".

Warning

This setting should be used only in the dev environment!

static_files_allowed

static_files_allowed: list[str | Pattern] | None

A list of file extensions (including the leading dot) that define which files within COMPONENTS.dirs or COMPONENTS.app_dirs are treated as static files.

If a file is matched against any of the patterns, it's considered a static file. Such files are collected when running collectstatic, and can be accessed under the static file endpoint.

You can also pass in compiled regexes (re.Pattern) for more advanced patterns.

By default, JS, CSS, and common image and font file formats are considered static files:

COMPONENTS = ComponentsSettings(
    static_files_allowed=[
        ".css",
        ".js", ".jsx", ".ts", ".tsx",
        # Images
        ".apng", ".png", ".avif", ".gif", ".jpg",
        ".jpeg",  ".jfif", ".pjpeg", ".pjp", ".svg",
        ".webp", ".bmp", ".ico", ".cur", ".tif", ".tiff",
        # Fonts
        ".eot", ".ttf", ".woff", ".otf", ".svg",
    ],
)

Warning

Exposing your Python files can be a security vulnerability. See Security notes.

forbidden_static_files

forbidden_static_files: list[str | Pattern] | None

Deprecated. Use COMPONENTS.static_files_forbidden instead.

static_files_forbidden

static_files_forbidden: list[str | Pattern] | None

A list of file extensions (including the leading dot) that define which files within COMPONENTS.dirs or COMPONENTS.app_dirs will NEVER be treated as static files.

If a file is matched against any of the patterns, it will never be considered a static file, even if the file matches a pattern in static_files_allowed.

Use this setting together with static_files_allowed for a fine control over what file types will be exposed.

You can also pass in compiled regexes (re.Pattern) for more advanced patterns.

By default, any HTML and Python are considered NOT static files:

COMPONENTS = ComponentsSettings(
    static_files_forbidden=[
        ".html", ".django", ".dj", ".tpl",
        # Python files
        ".py", ".pyc",
    ],
)

Warning

Exposing your Python files can be a security vulnerability. See Security notes.

tag_formatter

tag_formatter: TagFormatterABC | str | None

Configure what syntax is used inside Django templates to render components. See the available tag formatters.

Defaults to "django_components.component_formatter".

Learn more about Customizing component tags with TagFormatter.

Can be set either as direct reference:

from django_components import component_formatter

COMPONENTS = ComponentsSettings(
    "tag_formatter": component_formatter
)

Or as an import string;

COMPONENTS = ComponentsSettings(
    "tag_formatter": "django_components.component_formatter"
)

Example

  • "django_components.component_formatter"

    Set

    COMPONENTS = ComponentsSettings(
        "tag_formatter": "django_components.component_formatter"
    )
    

    To write components like this:

    {% component "button" href="..." %}
        Click me!
    {% endcomponent %}
    
  • django_components.component_shorthand_formatter

    Set

    COMPONENTS = ComponentsSettings(
        "tag_formatter": "django_components.component_shorthand_formatter"
    )
    

    To write components like this:

    {% button href="..." %}
        Click me!
    {% endbutton %}
    

template_cache_size

template_cache_size: int | None

DEPRECATED. Template caching will be removed in v1.

Configure the maximum amount of Django templates to be cached.

Defaults to 128.

Each time a Django template is rendered, it is cached to a global in-memory cache (using Python's lru_cache decorator). This speeds up the next render of the component. As the same component is often used many times on the same page, these savings add up.

By default the cache holds 128 component templates in memory, which should be enough for most sites. But if you have a lot of components, or if you are overriding Component.get_template() to render many dynamic templates, you can increase this number.

COMPONENTS = ComponentsSettings(
    template_cache_size=256,
)

To remove the cache limit altogether and cache everything, set template_cache_size to None.

COMPONENTS = ComponentsSettings(
    template_cache_size=None,
)

If you want to add templates to the cache yourself, you can use cached_template():

from django_components import cached_template

cached_template("Variable: {{ variable }}")

# You can optionally specify Template class, and other Template inputs:
class MyTemplate(Template):
    pass

cached_template(
    "Variable: {{ variable }}",
    template_cls=MyTemplate,
    name=...
    origin=...
    engine=...
)

ContextBehavior

ContextBehavior()

Bases: str, enum.Enum

See source code

Configure how (and whether) the context is passed to the component fills and what variables are available inside the {% fill %} tags.

Also see Component context and scope.

Options:

  • django: With this setting, component fills behave as usual Django tags.
  • isolated: This setting makes the component fills behave similar to Vue or React.

Attributes

DJANGO

With this setting, component fills behave as usual Django tags. That is, they enrich the context, and pass it along.

  1. Component fills use the context of the component they are within.
  2. Variables from Component.get_template_data() are available to the component fill.

Example

Given this template

{% with cheese="feta" %}
  {% component 'my_comp' %}
    {{ my_var }}  # my_var
    {{ cheese }}  # cheese
  {% endcomponent %}
{% endwith %}

and this context returned from the Component.get_template_data() method

{ "my_var": 123 }

Then if component "my_comp" defines context

{ "my_var": 456 }

Then this will render:

456   # my_var
feta  # cheese

Because "my_comp" overrides the variable "my_var", so {{ my_var }} equals 456.

And variable "cheese" will equal feta, because the fill CAN access the current context.

ISOLATED

This setting makes the component fills behave similar to Vue or React, where the fills use EXCLUSIVELY the context variables defined in Component.get_template_data().

Example

Given this template

{% with cheese="feta" %}
  {% component 'my_comp' %}
    {{ my_var }}  # my_var
    {{ cheese }}  # cheese
  {% endcomponent %}
{% endwith %}

and this context returned from the get_template_data() method

{ "my_var": 123 }

Then if component "my_comp" defines context

{ "my_var": 456 }

Then this will render:

123   # my_var
      # cheese

Because both variables "my_var" and "cheese" are taken from the root context. Since "cheese" is not defined in root context, it's empty.

Default

Default(value: Callable[[], Any])

Bases: object

See source code

Use this class to mark a field on the Component.Defaults class as a factory.

Read more about Component defaults.

Example

from django_components import Default

class MyComponent(Component):
    class Defaults:
        # Plain value doesn't need a factory
        position = "left"
        # Lists and dicts need to be wrapped in `Default`
        # Otherwise all instances will share the same value
        selected_items = Default(lambda: [1, 2, 3])

Attributes

value

value: Callable[[], Any]

DependenciesStrategy

DependenciesStrategy: TypeAlias

See source code

Type for the available strategies for rendering JS and CSS dependencies.

Read more about the dependencies strategies.

Dependency

Dependency(
    content: str | None,
    url: str | None = None,
    attrs: dict[str, str | bool] = dict(),
    kind: DependencyKind = 'extra',
    origin_class_id: str | None = None
)

Bases: object

See source code

Base class for JS/CSS dependency that will be rendered as <script>, <style>, or <link> tag.

The content of the dependency (JS/CSS) can be either:

  • Inlined as content (<script>...</script> or <style>...</style>)
  • Fetched from a URL (<script src="..."> or <link rel="stylesheet" href="...">)

Read more about Rendering JS and CSS.

Attributes

content

content: str | None

Text inside the <script> or <style> tag. Can be None for external dependencies.

url

url: str | None

If set, will render as <script src="..."> or <link rel="stylesheet" href="...">. Otherwise renders as <script>...</script> or <style>...</style>.

attrs

attrs: dict[str, str | bool]

Extra HTML attributes (values can be True for boolean attributes)

kind

Metadata about the kind of dependency:

  • "core": Required for Django Components library to work.
  • "component": Dependency from a component's Component.js or Component.css.
  • "variables": Dependency from a component's JS/CSS variables.
  • "extra": Any other dependencies, e.g. from Component.Media.js/css.

origin_class_id

origin_class_id: str | None

The class ID of the component that originated this dependency.

Methods

render

render() -> SafeString

See source code

Render as HTML tag.

render_json

render_json() -> dict[str, str | dict[str, str | bool]]

See source code

Render as JSON object with tag, attrs, and content fields.

DependencyKind

DependencyKind: TypeAlias

See source code

Type for the kind of Dependency objects.

  • "core": Required for Django Components library to work.
  • "component": Dependency from a component's Component.js or Component.css.
  • "variables": Dependency from a component's JS/CSS variables.
  • "extra": Any other dependencies, e.g. from Component.Media.js/css.

Empty

Empty()

Bases: tuple

See source code

Type for an object with no members.

You can use this to define Component types that accept NO args, kwargs, slots, etc:

from django_components import Component, Empty

class Table(Component):
    Args = Empty
    Kwargs = Empty
    ...

This class is a shorthand for:

class Empty(NamedTuple):
    pass

Read more about Typing and validation.

ExtensionComponentConfig

ExtensionComponentConfig(component: Component | None)

Bases: object

See source code

ExtensionComponentConfig is the base class for all extension component configs.

Extensions can define nested classes on the component class, such as Component.View or Component.Cache:

class MyComp(Component):
    class View:
        def get(self, request):
            ...

    class Cache:
        ttl = 60

This allows users to configure extension behavior per component.

Behind the scenes, the nested classes that users define on their components are merged with the extension's "base" class.

So the example above is the same as:

class MyComp(Component):
    class View(ViewExtension.ComponentConfig):
        def get(self, request):
            ...

    class Cache(CacheExtension.ComponentConfig):
        ttl = 60

Where both ViewExtension.ComponentConfig and CacheExtension.ComponentConfig are subclasses of ExtensionComponentConfig.

Attributes

component_cls

component_cls: type[Component]

The Component class that this extension is defined on.

component_class

component_class: type[Component]

The Component class that this extension is defined on.

componentproperty

component: Component

When a Component is instantiated, also the nested extension classes (such as Component.View) are instantiated, receiving the component instance as an argument.

This attribute holds the owner Component instance that this extension is defined on.

Some extensions like Storybook run outside of the component lifecycle, so there is no component instance available when running extension's methods. In such cases, this attribute will be None.

FillNode

FillNode(
    params: list[TagAttr],
    filters: dict[str, Callable[[Any, Any], Any]],
    tags: dict[str, Callable[[Any, Any], Any]],
    flags: dict[str, bool] | None = None,
    nodelist: NodeList | None = None,
    node_id: str | None = None,
    contents: str | None = None,
    template_name: str | None = None,
    template_component: type[Component] | None = None,
    start_tag_source: str | None = None
)

Bases: django_components.node.BaseNode

See source code

Use {% fill %} tag to insert content into component's slots.

{% fill %} tag may be used only within a {% component %}..{% endcomponent %} block, and raises a TemplateSyntaxError if used outside of a component.

ParameterTypeDescription
name(str, required)Name of the slot to insert this content into. Use "default" for the default slot.
datastrThis argument allows you to access the data passed to the slot under the specified variable name. See Slot data.
fallbackstrThis argument allows you to access the original content of the slot under the specified variable name. See Slot fallback.

Example

{% component "my_table" %}
  {% fill "pagination" %}
    < 1 | 2 | 3 >
  {% endfill %}
{% endcomponent %}

Access slot fallback

Use the fallback kwarg to access the original content of the slot.

The fallback kwarg defines the name of the variable that will contain the slot's fallback content.

Read more about Slot fallback.

Component template:

{# my_table.html #}
<table>
  ...
  {% slot "pagination" %}
    < 1 | 2 | 3 >
  {% endslot %}
</table>

Fill:

{% component "my_table" %}
  {% fill "pagination" fallback="fallback" %}
    <div class="my-class">
      {{ fallback }}
    </div>
  {% endfill %}
{% endcomponent %}

Access slot data

Use the data kwarg to access the data passed to the slot.

The data kwarg defines the name of the variable that will contain the slot's data.

Read more about Slot data.

Component template:

{# my_table.html #}
<table>
  ...
  {% slot "pagination" pages=pages %}
    < 1 | 2 | 3 >
  {% endslot %}
</table>

Fill:

{% component "my_table" %}
  {% fill "pagination" data="slot_data" %}
    {% for page in slot_data.pages %}
        <a href="{{ page.link }}">
          {{ page.index }}
        </a>
    {% endfor %}
  {% endfill %}
{% endcomponent %}

Using default slot

To access slot data and the fallback slot content on the default slot, use {% fill %} with name set to "default":

{% component "button" %}
  {% fill name="default" data="slot_data" fallback="slot_fallback" %}
    You clicked me {{ slot_data.count }} times!
    {{ slot_fallback }}
  {% endfill %}
{% endcomponent %}

Slot fills from Python

You can pass a slot fill from Python to a component by setting the body kwarg on the {% fill %} tag.

First pass a Slot instance to the template with the get_template_data() method:

from django_components import component, Slot

class Table(Component):
  def get_template_data(self, args, kwargs, slots, context):
    return {
        "my_slot": Slot(lambda ctx: "Hello, world!"),
    }

Then pass the slot to the {% fill %} tag:

{% component "table" %}
  {% fill "pagination" body=my_slot / %}
{% endcomponent %}

Warning

If you define both the body kwarg and the {% fill %} tag's body, an error will be raised.

{% component "table" %}
  {% fill "pagination" body=my_slot %}
    ...
  {% endfill %}
{% endcomponent %}

Attributes

Methods

render

render(
    context: Context,
    name: str,
    data: str | None = None,
    fallback: str | None = None,
    body: SlotInput | None = None,
    default: str | None = None
) -> str

OnRenderGenerator

OnRenderGenerator: TypeAlias

See source code

This is the signature of the Component.on_render() method if it yields (and thus returns a generator).

When on_render() is a generator then it:

  • Yields a rendered template (string or None) or a lambda function to be called later.

  • Receives back a tuple of (final_output, error).

    The final output is the rendered template that now has all its children rendered too. May be None if you yielded None earlier.

    The error is None if the rendering was successful. Otherwise the error is set and the output is None.

  • Can yield multiple times within the same method for complex rendering scenarios

  • At the end it may return a new string to override the final rendered output.

Example

from django_components import Component, OnRenderGenerator

class MyTable(Component):
    def on_render(
        self,
        context: Context,
        template: Template | None,
    ) -> OnRenderGenerator:
        # Do something BEFORE rendering template
        # Same as `Component.on_render_before()`
        context["hello"] = "world"

        # Yield a function that renders the template
        # to receive fully-rendered template or error.
        html, error = yield lambda: template.render(context)

        # Do something AFTER rendering template, or post-process
        # the rendered template.
        # Same as `Component.on_render_after()`
        if html is not None:
            return html + "<p>Hello</p>"

Multiple yields example:

class MyTable(Component):
    def on_render(self, context, template) -> OnRenderGenerator:
        # First yield
        with context.push({"mode": "header"}):
            header_html, header_error = yield lambda: template.render(context)

        # Second yield
        with context.push({"mode": "body"}):
            body_html, body_error = yield lambda: template.render(context)

        # Third yield
        footer_html, footer_error = yield "Footer content"

        # Process all results
        if header_error or body_error or footer_error:
            return "Error occurred during rendering"

        return f"{header_html}
{body_html}
{footer_html}"

ProvideNode

ProvideNode(
    params: list[TagAttr],
    filters: dict[str, Callable[[Any, Any], Any]],
    tags: dict[str, Callable[[Any, Any], Any]],
    flags: dict[str, bool] | None = None,
    nodelist: NodeList | None = None,
    node_id: str | None = None,
    contents: str | None = None,
    template_name: str | None = None,
    template_component: type[Component] | None = None,
    start_tag_source: str | None = None
)

Bases: django_components.node.BaseNode

See source code

The {% provide %} tag is part of the "provider" part of the provide / inject feature.

Pass kwargs to this tag to define the provider's data.

Any components defined within the {% provide %}..{% endprovide %} tags will be able to access this data with Component.inject().

This is similar to React's ContextProvider, or Vue's provide().

ParameterTypeDescription
name(str, required)Provider name. This is the name you will then use in Component.inject().
**kwargsAny extra kwargs will be passed as the provided data.

Example

Provide the "user_data" in parent component:

@register("parent")
class Parent(Component):
    template = """
      <div>
        {% provide "user_data" user=user %}
          {% component "child" / %}
        {% endprovide %}
      </div>
    """

    def get_template_data(self, args, kwargs, slots, context):
        return {
            "user": kwargs["user"],
        }

Since the "child" component is used within the {% provide %} / {% endprovide %} tags, we can request the "user_data" using Component.inject("user_data"):

@register("child")
class Child(Component):
    template = """
      <div>
        User is: {{ user }}
      </div>
    """

    def get_template_data(self, args, kwargs, slots, context):
        user = self.inject("user_data").user
        return {
            "user": user,
        }

Notice that the keys defined on the [{% provide %}](../template_tags/#provide) tag are then accessed as attributes when accessing them with [Component.inject()](#Component.inject).

✅ Do this

user = self.inject("user_data").user

❌ Don't do this

user = self.inject("user_data")["user"]

Attributes

Methods

render

render(
    context: Context,
    name: str,
    **kwargs: Any = {}
) -> SafeString

RegistrySettings

RegistrySettings()

Bases: tuple

See source code

Configuration for a ComponentRegistry.

These settings define how the components registered with this registry will behave when rendered.

from django_components import ComponentRegistry, RegistrySettings

registry_settings = RegistrySettings(
    context_behavior="django",
    tag_formatter="django_components.component_shorthand_formatter",
)

registry = ComponentRegistry(settings=registry_settings)

Attributes

context_behavior

context_behavior: ContextBehaviorType | None

Same as the global COMPONENTS.context_behavior setting, but for this registry.

If omitted, defaults to the global COMPONENTS.context_behavior setting.

CONTEXT_BEHAVIOR

CONTEXT_BEHAVIOR: ContextBehaviorType | None

Deprecated. Use context_behavior instead. Will be removed in v1.

Same as the global COMPONENTS.context_behavior setting, but for this registry.

If omitted, defaults to the global COMPONENTS.context_behavior setting.

tag_formatter

tag_formatter: TagFormatterABC | str | None

Same as the global COMPONENTS.tag_formatter setting, but for this registry.

If omitted, defaults to the global COMPONENTS.tag_formatter setting.

TAG_FORMATTER

TAG_FORMATTER: TagFormatterABC | str | None

Deprecated. Use tag_formatter instead. Will be removed in v1.

Same as the global COMPONENTS.tag_formatter setting, but for this registry.

If omitted, defaults to the global COMPONENTS.tag_formatter setting.

ReloadMode

ReloadMode()

Bases: str, enum.Enum

See source code

Configure how django_components reacts when component files (HTML templates, JS, CSS) change on disk while the dev server is running.

Also see Hot-reloading component files during development.

Options:

  • off: No file watching. Changes are not picked up until the server is manually restarted.
  • hot: Clear the in-memory component cache so the next render reads fresh content from disk. The dev server keeps running - no restart.
  • restart: Same as hot, but also restarts the dev server. Deprecated, will be removed in v1.

Attributes

OFF

No file watching. Component file changes are not picked up until the server is manually restarted.

HOT

Clear the in-memory component cache when a component file changes, so the next render reads fresh content from disk. The dev server keeps running without a restart.

RESTART

Same cache-clearing behavior as hot, but also triggers a full dev server restart.

Deprecated. Use hot instead. Will be removed in v1.

Script

Script(
    content: str | None,
    url: str | None = None,
    attrs: dict[str, str | bool] = dict(),
    kind: DependencyKind = 'extra',
    origin_class_id: str | None = None,
    wrap: bool = True
)

Bases: django_components.dependencies.Dependency

See source code

Represents a <script> tag with content and attributes.

Modify this object to change the attributes or content of the rendered <script> tag.

If Script.url is set, renders as <script src="...">, otherwise renders as <script>...</script>.

Example

from django_components import Script

script = Script(
    content="console.log('Hello, world!');",
    attrs={"type": "module"},
    wrap=False,
)

becomes

<script type="module">
    console.log('Hello, world!');
</script>

Attributes

wrap

wrap: bool

If True, wrap the JS content in a self-executing function. Only applies when the script type is absent or a JS MIME type.

See https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/script/type

Example

from django_components import Script

Script(
    content="console.log('Hello, world!');",
    wrap=True,
)

becomes

<script>
    (function() {
        console.log("Hello, world!");
    })();
</script>

Methods

to_json

to_json() -> dict

from_jsonclassmethod

from_json(data: dict) -> Script

Slot

Slot(
    contents: Any,
    content_func: SlotFunc[TSlotData] = cast('SlotFunc[TSlotData]', None),
    component_name: str | None = None,
    slot_name: str | None = None,
    nodelist: NodeList | None = None,
    fill_node: FillNode | ComponentNode | None = None,
    extra: dict[str, Any] = dict()
)

Bases: typing.Generic

See source code

This class is the main way for defining and handling slots.

It holds the slot content function along with related metadata.

Read more about Slot class.

Example

Passing slots to components:

from django_components import Slot

slot = Slot(lambda ctx: f"Hello, {ctx.data['name']}!")

MyComponent.render(
    slots={
        "my_slot": slot,
    },
)

Accessing slots inside the components:

from django_components import Component

class MyComponent(Component):
    def get_template_data(self, args, kwargs, slots, context):
        my_slot = slots["my_slot"]
        return {
            "my_slot": my_slot,
        }

Rendering slots:

from django_components import Slot

slot = Slot(lambda ctx: f"Hello, {ctx.data['name']}!")
html = slot({"name": "John"})  # Output: Hello, John!

Attributes

contents

contents: Any

The original value that was passed to the Slot constructor.

  • If Slot was created from {% fill %} tag, Slot.contents will contain the body (string) of that {% fill %} tag.
  • If Slot was created from string as Slot("..."), Slot.contents will contain that string.
  • If Slot was created from a function, Slot.contents will contain that function.

Read more about Slot contents.

content_func

content_func: SlotFunc[TSlotData]

The actual slot function.

Do NOT call this function directly, instead call the Slot instance as a function.

Read more about Rendering slot functions.

component_name

component_name: str | None

Name of the component that originally received this slot fill.

See Slot metadata.

slot_name

slot_name: str | None

Slot name to which this Slot was initially assigned.

See Slot metadata.

nodelist

nodelist: NodeList | None

If the slot was defined with {% fill %} tag, this will be the Nodelist of the fill's content.

See Slot metadata.

fill_node

fill_node: FillNode | ComponentNode | None

If the slot was created from a {% fill %} tag, this will be the FillNode instance.

If the slot was a default slot created from a {% component %} tag, this will be the ComponentNode instance.

Otherwise, this will be None.

Extensions can use this info to handle slots differently based on their source.

See Slot metadata.

Example

You can use this to find the [Component](#Component) in whose template the {% fill %} tag was defined:

class MyTable(Component):
    def get_template_data(self, args, kwargs, slots, context):
        footer_slot = slots.get("footer")
        if footer_slot is not None and footer_slot.fill_node is not None:
            owner_component = footer_slot.fill_node.template_component
            # ...

extra

extra: dict[str, Any]

Dictionary that can be used to store arbitrary metadata about the slot.

See Slot metadata.

See Pass slot metadata for usage for extensions.

Example

# Either at slot creation
slot = Slot(lambda ctx: "Hello, world!", extra={"foo": "bar"})

# Or later
slot.extra["baz"] = "qux"

do_not_call_in_templatesproperty

do_not_call_in_templates: bool

Django special property to prevent calling the instance as a function inside Django templates.

SlotContent

SlotContent: TypeAlias

See source code

DEPRECATED: Use SlotInput instead. Will be removed in v1.

SlotContext

SlotContext(
    data: TSlotData,
    fallback: str | SlotFallback | None = None,
    context: Context | None = None
)

Bases: typing.Generic

See source code

Metadata available inside slot functions.

Read more about Slot functions.

Example

from django_components import SlotContext, SlotResult

def my_slot(ctx: SlotContext) -> SlotResult:
    return f"Hello, {ctx.data['name']}!"

You can pass a type parameter to the SlotContext to specify the type of the data passed to the slot:

class MySlotData(TypedDict):
    name: str

def my_slot(ctx: SlotContext[MySlotData]):
    return f"Hello, {ctx.data['name']}!"

Attributes

data

data: TSlotData

Data passed to the slot.

Read more about Slot data.

Example

def my_slot(ctx: SlotContext):
    return f"Hello, {ctx.data['name']}!"

fallback

fallback: str | SlotFallback | None

Slot's fallback content. Lazily-rendered - coerce this value to string to force it to render.

Read more about Slot fallback.

Example

def my_slot(ctx: SlotContext):
    return f"Hello, {ctx.fallback}!"

May be None if you call the slot fill directly, without using {% slot %} tags.

context

context: Context | None

Django template Context available inside the {% fill %} tag.

May be None if you call the slot fill directly, without using {% slot %} tags.

SlotFallback

SlotFallback(slot: SlotNode, context: Context)

Bases: object

See source code

The content between the {% slot %}..{% endslot %} tags is the fallback content that will be rendered if no fill is given for the slot.

{% slot "name" %}
    Hello, my name is {{ name }}  <!-- Fallback content -->
{% endslot %}

Because the fallback is defined as a piece of the template (NodeList), we want to lazily render it only when needed.

SlotFallback type allows to pass around the slot fallback as a variable.

To force the fallback to render, coerce it to string to trigger the __str__() method.

Example

def slot_function(self, ctx: SlotContext):
    return f"Hello, {ctx.fallback}!"

SlotFunc

SlotFunc()

Bases: typing.Protocol

See source code

When rendering components with Component.render() or Component.render_to_response(), the slots can be given either as strings or as functions.

If a slot is given as a function, it will have the signature of SlotFunc.

Read more about Slot functions.

ParameterTypeDescription
ctxSlotContextSingle named tuple that holds the slot data and metadata.

Returns

  • str | SafeString – The rendered slot content.

Example

from django_components import SlotContext, SlotResult

def header(ctx: SlotContext) -> SlotResult:
    if ctx.data.get("name"):
        return f"Hello, {ctx.data['name']}!"
    else:
        return ctx.fallback

html = MyTable.render(
    slots={
        "header": header,
    },
)

SlotInput

SlotInput: TypeAlias

See source code

Type representing all forms in which slot content can be passed to a component.

When rendering a component with Component.render() or Component.render_to_response(), the slots may be given a strings, functions, or Slot instances. This type describes that union.

Use this type when typing the slots in your component.

SlotInput accepts an optional type parameter to specify the data dictionary that will be passed to the slot content function.

Example

from typing import TypedDict
from django_components import Component, SlotInput

class TableFooterSlotData(TypedDict):
    page_number: int

class Table(Component):
    class Slots:
        header: SlotInput
        footer: SlotInput[TableFooterSlotData]

    template = "<div>{% slot 'footer' %}</div>"

html = Table.render(
    slots={
        # As a string
        "header": "Hello, World!",

        # Safe string
        "header": mark_safe("<i><am><safe>"),

        # Function
        "footer": lambda ctx: f"Page: {ctx.data['page_number']}!",

        # Slot instance
        "footer": Slot(lambda ctx: f"Page: {ctx.data['page_number']}!"),

        # None (Same as no slot)
        "header": None,
    },
)

SlotNode

SlotNode(
    params: list[TagAttr],
    filters: dict[str, Callable[[Any, Any], Any]],
    tags: dict[str, Callable[[Any, Any], Any]],
    flags: dict[str, bool] | None = None,
    nodelist: NodeList | None = None,
    node_id: str | None = None,
    contents: str | None = None,
    template_name: str | None = None,
    template_component: type[Component] | None = None,
    start_tag_source: str | None = None
)

Bases: django_components.node.BaseNode

See source code

{% slot %} tag marks a place inside a component where content can be inserted from outside.

Learn more about using slots.

This is similar to slots as seen in Web components, Vue or React's children.

ParameterTypeDescription
name(str, required)Registered name of the component to render
defaultOptional flag. If there is a default slot, you can pass the component slot content without using the {% fill %} tag. See Default slot
requiredOptional flag. Will raise an error if a slot is required but not given.
**kwargsAny extra kwargs will be passed as the slot data.

Example

@register("child")
class Child(Component):
    template = """
      <div>
        {% slot "content" default %}
          This is shown if not overriden!
        {% endslot %}
      </div>
      <aside>
        {% slot "sidebar" required / %}
      </aside>
    """
@register("parent")
class Parent(Component):
    template = """
      <div>
        {% component "child" %}
          {% fill "content" %}
            🗞️📰
          {% endfill %}

          {% fill "sidebar" %}
            🍷🧉🍾
          {% endfill %}
        {% endcomponent %}
      </div>
    """

Slot data

Any extra kwargs will be considered as slot data, and will be accessible in the {% fill %} tag via fill's data kwarg:

Read more about Slot data.

@register("child")
class Child(Component):
    template = """
      <div>
        {# Passing data to the slot #}
        {% slot "content" user=user %}
          This is shown if not overriden!
        {% endslot %}
      </div>
    """
@register("parent")
class Parent(Component):
    template = """
      {# Parent can access the slot data #}
      {% component "child" %}
        {% fill "content" data="data" %}
          <div class="wrapper-class">
            {{ data.user }}
          </div>
        {% endfill %}
      {% endcomponent %}
    """

Slot fallback

The content between the {% slot %}..{% endslot %} tags is the fallback content that will be rendered if no fill is given for the slot.

This fallback content can then be accessed from within the {% fill %} tag using the fill's fallback kwarg. This is useful if you need to wrap / prepend / append the original slot's content.

@register("child")
class Child(Component):
    template = """
      <div>
        {% slot "content" %}
          This is fallback content!
        {% endslot %}
      </div>
    """
@register("parent")
class Parent(Component):
    template = """
      {# Parent can access the slot's fallback content #}
      {% component "child" %}
        {% fill "content" fallback="fallback" %}
          {{ fallback }}
        {% endfill %}
      {% endcomponent %}
    """

Attributes

Methods

render

render(
    context: Context,
    name: str,
    **kwargs: Any = {}
) -> SafeString

SlotRef

SlotRef: TypeAlias

See source code

DEPRECATED: Use SlotFallback instead. Will be removed in v1.

SlotResult

SlotResult: TypeAlias

See source code

Type representing the result of a slot render function.

Example

from django_components import SlotContext, SlotResult

def my_slot_fn(ctx: SlotContext) -> SlotResult:
    return "Hello, world!"

my_slot = Slot(my_slot_fn)
html = my_slot()  # Output: Hello, world!

Read more about Slot functions.

Style

Style(
    content: str | None,
    url: str | None = None,
    attrs: dict[str, str | bool] = dict(),
    kind: DependencyKind = 'extra',
    origin_class_id: str | None = None
)

Bases: django_components.dependencies.Dependency

See source code

Represents a <style> tag or <link rel="stylesheet"> tag for stylesheets.

Modify this object to change the attributes or content of the rendered <link> or <style> tag.

If Style.url is set, renders as <link rel="stylesheet" href="...">, otherwise renders as <style>...</style>.

Example

from django_components import Style

style = Style(
    url="/static/style.css",
    attrs={"media": "print"},
)

becomes

<link rel="stylesheet" href="/static/style.css" media="print">

Methods

to_json

to_json() -> dict

from_jsonclassmethod

from_json(data: dict) -> Style

render

render() -> SafeString

TagFormatterABC

TagFormatterABC()

Bases: abc.ABC

See source code

Abstract base class for defining custom tag formatters.

Tag formatters define how the component tags are used in the template.

Read more about Tag formatter.

For example, with the default tag formatter (ComponentFormatter), components are written as:

{% component "comp_name" %}
{% endcomponent %}

While with the shorthand tag formatter (ShorthandComponentFormatter), components are written as:

{% comp_name %}
{% endcomp_name %}

Example

Implementation for ShorthandComponentFormatter:

from djagno_components import TagFormatterABC, TagResult

class ShorthandComponentFormatter(TagFormatterABC):
    def start_tag(self, name: str) -> str:
        return name

    def end_tag(self, name: str) -> str:
        return f"end{name}"

    def parse(self, tokens: list[str]) -> TagResult:
        tokens = [*tokens]
        name = tokens.pop(0)
        return TagResult(name, tokens)

Methods

start_tag

start_tag(name: str) -> str

See source code

Formats the start tag of a component.

ParameterTypeDescription
namestrComponent's registered name. Required.

Returns

  • str – The formatted start tag.

end_tag

end_tag(name: str) -> str

See source code

Formats the end tag of a block component.

ParameterTypeDescription
namestrComponent's registered name. Required.

Returns

  • str – The formatted end tag.

parse

parse(tokens: list[str]) -> TagResult

See source code

Given the tokens (words) passed to a component start tag, this function extracts the component name from the tokens list, and returns TagResult, which is a tuple of (component_name, remaining_tokens).

ParameterTypeDescription
tokenslist[str]List of tokens passed to the component tag.

Returns

  • TagResult – Parsed component name and remaining tokens.

Example

Assuming we used a component in a template like this:

{% component "my_comp" key=val key2=val2 %}
{% endcomponent %}

This function receives a list of tokens:

['component', '"my_comp"', 'key=val', 'key2=val2']
  • component is the tag name, which we drop.
  • "my_comp" is the component name, but we must remove the extra quotes.
  • The remaining tokens we pass unmodified, as that's the input to the component.

So in the end, we return:

TagResult('my_comp', ['key=val', 'key2=val2'])

TagResult

TagResult()

Bases: tuple

See source code

The return value from TagFormatter.parse().

Read more about Tag formatters.

Attributes

component_name

component_name: str

Component name extracted from the template tag

For example, if we had tag

{% component "my_comp" key=val key2=val2 %}

Then component_name would be my_comp.

tokens

tokens: list[str]

Remaining tokens (words) that were passed to the tag, with component name removed

For example, if we had tag

{% component "my_comp" key=val key2=val2 %}

Then tokens would be ['key=val', 'key2=val2'].

all_components

all_components() -> list[type[Component]]

See source code

Get a list of all created Component classes.

all_registries

all_registries() -> list[ComponentRegistry]

See source code

Get a list of all created ComponentRegistry instances.

autodiscover

autodiscover(map_module: Callable[[str], str] | None = None) -> list[str]

See source code

Search for all python files in COMPONENTS.dirs and COMPONENTS.app_dirs and import them.

See Autodiscovery.

NOTE: Subdirectories and files starting with an underscore _ (except for __init__.py are ignored.

ParameterTypeDescription
map_moduleCallable[[str], str] | NoneMap the module paths with map_module function. This serves as an escape hatch for when you need to use this function in tests. (default: None)

Returns

  • list[str] – list[str]: A list of module paths of imported files.

To get the same list of modules that autodiscover() would return, but without importing them, use get_component_files():

from django_components import get_component_files

modules = get_component_files(".py")

cached_template

cached_template(
    template_string: str,
    template_cls: type[Template] | None = None,
    origin: Origin | None = None,
    name: str | None = None,
    engine: Any | None = None
) -> Template

See source code

DEPRECATED. Template caching will be removed in v1.

Create a Template instance that will be cached as per the COMPONENTS.template_cache_size setting.

ParameterTypeDescription
template_stringstrTemplate as a string, same as the first argument to Django's Template. Required.
template_clstype[Template] | NoneSpecify the Template class that should be instantiated. Defaults to Django's Template class. (default: None)
originOrigin | NoneSets Template.Origin. (default: None)
namestr | NoneSets Template.name (default: None)
engineAny | NoneSets Template.engine (default: None)
from django_components import cached_template

template = cached_template("Variable: {{ variable }}")

# You can optionally specify Template class, and other Template inputs:
class MyTemplate(Template):
    pass

template = cached_template(
    "Variable: {{ variable }}",
    template_cls=MyTemplate,
    name=...
    origin=...
    engine=...
)

compose_attrs

compose_attrs(*attrs: AttrsSource = ()) -> AttrsDict

See source code

Compose HTML attribute mappings from left to right.

Arguments may be mappings or arbitrarily nested lists or tuples whose terminal values are mappings. Ordinary keys use the last value without changing their first-seen order. All class and style values are collected and normalized, so each source can contribute classes and style properties independently.

None contributes nothing to class and style. As with ordinary HTML attributes, None and False values are omitted when the returned AttrsDict is rendered, while True renders a bare attribute.

Unlike the legacy merge_attributes(), this function does not join collisions for ordinary attributes with spaces.

Example

compose_attrs(
    [{"id": "first", "class": "button"}, [{"class": {"active": True}}]],
    {"id": "last"},
)
# == {"id": "last", "class": "button active"}

Raises

  • TypeError – If a terminal value is not a mapping, or an attribute name is not a string.
  • ValueError – If the source containers are cyclic, or an attribute name is invalid.

format_attributes

format_attributes(attributes: Mapping[str, Any]) -> str

See source code

Format a mapping of attributes into an HTML attributes string.

Attribute names must be strings and valid HTML attribute names. class and style accept structured values and are normalized before rendering. Empty normalized class and style values are omitted.

Read more about HTML attributes.

Example

format_attributes({"class": "my-class", "data-id": "123"})

will return

'class="my-class" data-id="123"'

get_component_by_class_id

get_component_by_class_id(comp_cls_id: str) -> type[Component]

See source code

Get a component class by its unique ID.

Each component class is associated with a unique hash that's derived from its module import path.

E.g. path.to.my.secret.MyComponent -> MyComponent_ab01f32

This hash is available under class_id on the component class.

Raises KeyError if the component class is not found.

NOTE: This is mainly intended for extensions.

get_component_defaults

get_component_defaults(component: type[Component] | Component) -> dict[str, Any]

See source code

Generate a defaults dictionary for a Component.

The defaults dictionary is generated from the Component.Defaults and Component.Kwargs classes. Kwargs take precedence over Defaults.

Read more about Component defaults.

Example

from django_components import Component, Default, get_component_defaults

class MyTable(Component):
    class Kwargs:
        position: str
        order: int
        items: list[int]
        variable: str = "from_kwargs"

    class Defaults:
        position: str = "left"
        items = Default(lambda: [1, 2, 3])

# Get the defaults dictionary
defaults = get_component_defaults(MyTable)
# {
#     "position": "left",
#     "items": [1, 2, 3],
#     "variable": "from_kwargs",
# }

get_component_dirs

get_component_dirs(include_apps: bool = True) -> list[Path]

See source code

Get directories that may contain component files.

This is the heart of all features that deal with filesystem and file lookup. Autodiscovery, Django template resolution, static file resolution - They all use this.

ParameterTypeDescription
include_appsboolInclude directories from installed Django apps. Defaults to True. (default: True)

Returns

  • list[Path] – list[Path]: A list of directories that may contain component files.

get_component_dirs() searches for dirs set in COMPONENTS.dirs settings. If none set, defaults to searching for a "components" app.

In addition to that, also all installed Django apps are checked whether they contain directories as set in COMPONENTS.app_dirs (e.g. [app]/components).

Notes:

  • Paths that do not point to directories are ignored.

  • BASE_DIR setting is required.

  • The paths in COMPONENTS.dirs must be absolute paths.

get_component_files

get_component_files(suffix: str | None = None) -> list[ComponentFileEntry]

See source code

Search for files within the component directories (as defined in get_component_dirs()).

Requires BASE_DIR setting to be set.

Subdirectories and files starting with an underscore _ (except __init__.py) are ignored.

ParameterTypeDescription
suffixstr | NoneThe suffix to search for. E.g. .py, .js, .css. Defaults to None, which will search for all files. (default: None)

Returns

  • list[ComponentFileEntry] – list[ComponentFileEntry] A list of entries that contain both the filesystem path and the python import path (dot path).

Example

from django_components import get_component_files

modules = get_component_files(".py")

get_component_url

get_component_url(
    component: type[Component] | Component,
    query: dict | None = None,
    fragment: str | None = None,
    args: Sequence[Any] | None = None,
    kwargs: Mapping[str, Any] | None = None
) -> str

See source code

Get the URL for a Component.

Raises RuntimeError if the component is not public.

Component is public when:

Read more about Component views and URLs.

get_component_url() optionally accepts query and fragment arguments.

get_component_url() also accepts optionally args and kwargs arguments that will be transmitted to django.urls.reverse.

Query parameter handling:

  • True values are rendered as flag parameters without values (e.g., ?enabled)
  • False and None values are omitted from the URL
  • Other values are rendered normally (e.g., ?foo=bar)

Example

from django_components import Component, get_component_url

class MyTable(Component):
    class View:
        def get(self, request: HttpRequest, **kwargs: Any):
            return MyTable.render_to_response()

# Get the URL for the component
url = get_component_url(
    MyComponent,
    query={"foo": "bar", "enabled": True, "debug": False, "unused": None},
    fragment="baz",
)
# /components/ext/view/components/c1ab2c3/?foo=bar&enabled#baz

Example with route parameters:

If your component defines a custom route path with parameters using get_route_path(), you can pass args and kwargs to fill those parameters:

from django_components import Component, get_component_url

class UserProfile(Component):
    class View:
        @classmethod
        def get_route_path(cls):
            return f"users/{cls.component_cls.class_id}/<str:username>/<int:user_id>/"

        def get(self, request: HttpRequest, username: str, user_id: int, **kwargs: Any):
            return UserProfile.render_to_response()

# Get the URL with route parameters filled
url = get_component_url(
    UserProfile,
    kwargs={"username": "john", "user_id": 42},
    query={"tab": "settings"},
)
# /components/ext/view/components/c1ab2c3/john/42/?tab=settings

import_libraries

import_libraries(map_module: Callable[[str], str] | None = None) -> list[str]

See source code

Import modules set in COMPONENTS.libraries setting.

See Autodiscovery.

ParameterTypeDescription
map_moduleCallable[[str], str] | NoneMap the module paths with map_module function. This serves as an escape hatch for when you need to use this function in tests. (default: None)

Returns

  • list[str] – list[str]: A list of module paths of imported files.

Example

Normal usage - load libraries after Django has loaded

from django_components import import_libraries

class MyAppConfig(AppConfig):
    def ready(self):
        import_libraries()

Potential usage in tests

from django_components import import_libraries

import_libraries(lambda path: path.replace("tests.", "myapp."))

merge_attributes

merge_attributes(*attrs: dict = ()) -> dict

See source code

Merge a list of dictionaries into a single dictionary.

The dictionaries are treated as HTML attributes and are merged accordingly:

  • If a same key is present in multiple dictionaries, the values are joined with a space character.
  • The class and style keys are handled specially, similar to how Vue does it.

Read more about HTML attributes.

Example

merge_attributes(
    {"my-attr": "my-value", "class": "my-class"},
    {"my-attr": "extra-value", "data-id": "123"},
)

will result in

{
    "my-attr": "my-value extra-value",
    "class": "my-class",
    "data-id": "123",
}

The class attribute

The class attribute can be given as a string, or a dictionary.

  • If given as a string, it is used as is.
  • If given as a dictionary, only the keys with a truthy value are used.

Example

merge_attributes(
    {"class": "my-class extra-class"},
    {"class": {"truthy": True, "falsy": False}},
)

will result in

{
    "class": "my-class extra-class truthy",
}

The style attribute

The style attribute can be given as a string, a list, or a dictionary.

  • If given as a string, it is used as is.
  • If given as a dictionary, it is converted to a style attribute string.

Example

merge_attributes(
    {"style": "color: red; background-color: blue;"},
    {"style": {"background-color": "green", "color": False}},
)

will result in

{
    "style": "color: red; background-color: blue; background-color: green;",
}

register

register(name: str, registry: ComponentRegistry | None = None) -> Callable[[type[TComponent]], type[TComponent]]

See source code

Class decorator for registering a component to a component registry.

See Registering components.

ParameterTypeDescription
namestrRegistered name. This is the name by which the component will be accessed from within a template when using the {% component %} tag. Required.
registryComponentRegistry | NoneSpecify the registry to which to register this component. If omitted, component is registered to the default registry. (default: None)

Raises

  • AlreadyRegistered – If there is already a component registered under the same name.

Examples:

from django_components import Component, register

@register("my_component")
class MyComponent(Component):
    ...

Specifing ComponentRegistry the component should be registered to by setting the registry kwarg:

from django.template import Library
from django_components import Component, ComponentRegistry, register

my_lib = Library()
my_reg = ComponentRegistry(library=my_lib)

@register("my_component", registry=my_reg)
class MyComponent(Component):
    ...

registry

See source code

The default and global component registry. Use this instance to directly register or remove components:

See Registering components.

# Register components
registry.register("button", ButtonComponent)
registry.register("card", CardComponent)

# Get single
registry.get("button")

# Get all
registry.all()

# Check if component is registered
registry.has("button")

# Unregister single
registry.unregister("button")

# Unregister all
registry.clear()

render_dependencies

render_dependencies(content: TContent, strategy: DependenciesStrategy = 'document') -> TContent

See source code

Given an HTML string (str or bytes) that contains parts that were rendered by components, this function searches the HTML for the components used in the rendering, and inserts the JS and CSS of the used components into the HTML.

Returns the edited copy of the HTML.

See Rendering JS / CSS.

ParameterTypeDescription
contentTContentThe rendered HTML string that is searched for components, and into which we insert the JS and CSS tags. Required.
strategyDependenciesStrategy

Optional. Configure how to handle JS and CSS dependencies. Default is "document". Read more about Rendering strategies.

There are six strategies:

  • "document" (default for top-level)
    • Smartly inserts JS / CSS into placeholders or into <head> and <body> tags.
    • Inserts extra script to allow fragment types to work.
    • Assumes the HTML will be rendered in a JS-enabled browser.
  • "fragment"
    • A lightweight HTML fragment to be inserted into a document.
    • No JS / CSS included.
  • "simple"
    • Smartly insert JS / CSS into placeholders or into <head> and <body> tags.
    • No extra script loaded.
  • "prepend"
    • Insert JS / CSS before the rendered HTML.
    • No extra script loaded.
  • "append"
    • Insert JS / CSS after the rendered HTML.
    • No extra script loaded.
  • "ignore" (default when nested)
    • Returns the content unchanged (no JS / CSS inserted).
(default: 'document')

Example

def my_view(request):
    template = Template('''
        {% load component_tags %}
        <!doctype html>
        <html>
            <head></head>
            <body>
                <h1>{{ table_name }}</h1>
                {% component "table" name=table_name / %}
            </body>
        </html>
    ''')

    html = template.render(
        Context({
            "table_name": request.GET["name"],
        })
    )

    # This inserts components' JS and CSS
    processed_html = render_dependencies(html)

    return HttpResponse(processed_html)

template_tag

template_tag(
    library: Library,
    tag: str,
    end_tag: str | None = None,
    allowed_flags: Iterable[str] | None = None
) -> Callable[[Callable], Callable]

See source code

A simplified version of creating a template tag based on BaseNode.

Instead of defining the whole class, you can just define the render() method.

from django.template import Context, Library
from django_components import BaseNode, template_tag

library = Library()

@template_tag(
    library,
    tag="mytag",
    end_tag="endmytag",
    allowed_flags=["required"],
)
def mytag(node: BaseNode, context: Context, name: str, **kwargs: Any) -> str:
    return f"Hello, {name}!"

This will allow the template tag {% mytag %} to be used like this:

{% mytag name="John" %}
{% mytag name="John" required %} ... {% endmytag %}

The given function will be wrapped in a class that inherits from BaseNode.

And this class will be registered with the given library.

The function MUST accept at least two positional arguments: node and context

Any extra parameters defined on this function will be part of the tag's input parameters.

For more info, see BaseNode.render().

django-components version: 0.152.0