Skip to content

API¤

BaseNode ¤

BaseNode(
    params: List[TagAttr],
    flags: Optional[Dict[str, bool]] = None,
    nodelist: Optional[NodeList] = None,
    node_id: Optional[str] = None,
    contents: Optional[str] = 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().

Methods:

Attributes:

active_flags property ¤

active_flags: List[str]

See source code

Flags that were set for this specific instance.

allowed_flags class-attribute instance-attribute ¤

allowed_flags: Optional[List[str]] = None

See source code

The allowed flags for this tag.

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

contents instance-attribute ¤

contents = contents

end_tag class-attribute instance-attribute ¤

end_tag: Optional[str] = None

See source code

The end tag name.

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

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

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

flags instance-attribute ¤

flags = flags or {flag: Falsefor flag in allowed_flags or []}

node_id instance-attribute ¤

node_id = node_id or gen_id()

nodelist instance-attribute ¤

nodelist = nodelist or NodeList()

params instance-attribute ¤

params = params

tag instance-attribute ¤

tag: str

See source code

The tag name.

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

parse classmethod ¤

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().

register classmethod ¤

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 %}

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 %}

unregister classmethod ¤

unregister(library: Library) -> None

See source code

Unregisters the node from the given library.

CommandLiteralAction module-attribute ¤

CommandLiteralAction = Literal['append', 'append_const', 'count', 'extend', 'store', 'store_const', 'store_true', 'store_false', 'version']

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: Optional[str] = None, outer_context: Optional[Context] = None, registry: Optional[ComponentRegistry] = None)

Methods:

Attributes:

Args class-attribute instance-attribute ¤

Args: Type = cast(Type, None)

See source code

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 typing import NamedTuple
from django_components import Component

class Table(Component):
    class Args(NamedTuple):
        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,
        }

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.

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

Read more on Typing and validation.

Cache instance-attribute ¤

See source code

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"

CssData class-attribute instance-attribute ¤

CssData: Type = cast(Type, None)

See source code

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.

The constructor of this class MUST accept keyword arguments:

CssData(**css_data)

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

from typing import NamedTuple
from django_components import Component

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

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

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

Use CssData to:

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

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)
    

Defaults instance-attribute ¤

See source code

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

JsData class-attribute instance-attribute ¤

JsData: Type = cast(Type, None)

See source code

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.

The constructor of this class MUST accept keyword arguments:

JsData(**js_data)

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

from typing import NamedTuple
from django_components import Component

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

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

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

Use JsData to:

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

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)
    

Kwargs class-attribute instance-attribute ¤

Kwargs: Type = cast(Type, None)

See source code

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 typing import NamedTuple
from django_components import Component

class Table(Component):
    class Kwargs(NamedTuple):
        color: str
        size: int

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

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

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.

Use Kwargs to:

  • Validate the input at runtime.
  • Set type hints for the keyword arguments for data methods like get_template_data().
  • 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),
)

Read more on Typing and validation.

Media class-attribute instance-attribute ¤

See source code

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"],
        }

Slots class-attribute instance-attribute ¤

Slots: Type = cast(Type, None)

See source code

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 typing import NamedTuple
from django_components import Component, Slot, SlotInput

class Table(Component):
    class Slots(NamedTuple):
        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,
        }

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.

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: ...),
    ),
)

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.

TemplateData class-attribute instance-attribute ¤

TemplateData: Type = cast(Type, None)

See source code

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.

The constructor of this class MUST accept keyword arguments:

TemplateData(**template_data)

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

from typing import NamedTuple
from django_components import Component

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

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

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

Use TemplateData to:

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

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)
    

View instance-attribute ¤

See source code

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

cache instance-attribute ¤

See source code

Instance of ComponentCache available at component render time.

class_id class-attribute ¤

class_id: str

See source code

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.

context_processors_data property ¤

context_processors_data: Dict

See source code

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.

Raises RuntimeError if accessed outside of rendering execution.

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,
        }

css class-attribute instance-attribute ¤

css: Optional[str] = None

See source code

Main CSS associated with this component inlined as string.

Only one of css or css_file must be defined.

Example:

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

css_file class-attribute instance-attribute ¤

css_file: Optional[str] = None

See source code

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.

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;
# };

defaults instance-attribute ¤

See source code

Instance of ComponentDefaults available at component render time.

id property ¤

id: str

See source code

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

This is useful for logging or debugging.

Raises RuntimeError if accessed outside of rendering execution.

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 property ¤

See source code

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

Raises RuntimeError if accessed outside of rendering execution.

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

Read more on Component inputs.

Example:

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

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

is_filled property ¤

is_filled: SlotIsFilled

See source code

Dictionary describing which slots have or have not been filled.

This attribute is available for use only within the template as {{ component_vars.is_filled.slot_name }}, and within on_render_before and on_render_after hooks.

Raises RuntimeError if accessed outside of rendering execution.

js class-attribute instance-attribute ¤

js: Optional[str] = None

See source code

Main JS associated with this component inlined as string.

Only one of js or js_file must be defined.

Example:

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

js_file class-attribute instance-attribute ¤

js_file: Optional[str] = None

See source code

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.

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!');

media class-attribute instance-attribute ¤

media: Optional[Media] = None

See source code

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 HTML / 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 class-attribute instance-attribute ¤

media_class: Type[Media] = Media

See source code

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 Defining HTML / JS / CSS files.

Example:

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

    media_class = MyMediaClass

name property ¤

name: str

outer_context instance-attribute ¤

outer_context: Optional[Context] = outer_context

registered_name instance-attribute ¤

registered_name: Optional[str] = registered_name

registry instance-attribute ¤

registry = registry or registry

request property ¤

See source code

HTTPRequest object passed to this component.

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

But in 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.

Raises RuntimeError if accessed outside of rendering execution.

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,
        }

response_class class-attribute instance-attribute ¤

response_class = HttpResponse

See source code

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)

template class-attribute instance-attribute ¤

template: Optional[Union[str, Template]] = None

See source code

Inlined Django template associated with this component. Can be a plain string or a Template instance.

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

Example:

class MyComponent(Component):
    template = "Hello, {{ name }}!"

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

template_file class-attribute instance-attribute ¤

template_file: Optional[str] = None

See source code

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/).

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

Example:

class MyComponent(Component):
    template_file = "path/to/template.html"

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

template_name instance-attribute ¤

template_name: Optional[str]

See source code

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.

view instance-attribute ¤

See source code

Instance of ComponentView available at component render time.

as_view classmethod ¤

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.

get_context_data ¤

get_context_data(*args: Any, **kwargs: Any) -> Optional[Mapping]

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_css_data ¤

get_css_data(args: Any, kwargs: Any, slots: Any, context: Context) -> Optional[Mapping]

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

Args:

  • args: Positional arguments passed to the component.
  • kwargs: Keyword arguments passed to the component.
  • slots: Slots passed to the component.
  • context: 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 typing import NamedTuple
from django.template import Context
from django_components import Component, SlotInput

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

    class Kwargs(NamedTuple):
        size: int

    class Slots(NamedTuple):
        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(NamedTuple):
        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"],
        )

get_js_data ¤

get_js_data(args: Any, kwargs: Any, slots: Any, context: Context) -> Optional[Mapping]

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 = '''
        $onLoad(({ name, id }) => {
            console.log(name, id);
        });
    '''

MyComponent.render(name="World")

Args:

  • args: Positional arguments passed to the component.
  • kwargs: Keyword arguments passed to the component.
  • slots: Slots passed to the component.
  • context: 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(NamedTuple):
        color: str

    class Kwargs(NamedTuple):
        size: int

    class Slots(NamedTuple):
        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(NamedTuple):
        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_template ¤

get_template(context: Context) -> Optional[Union[str, Template]]

See source code

Inlined Django template associated with this component. Can be a plain string or a Template instance.

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

get_template_data ¤

get_template_data(args: Any, kwargs: Any, slots: Any, context: Context) -> Optional[Mapping]

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

Args:

  • args: Positional arguments passed to the component.
  • kwargs: Keyword arguments passed to the component.
  • slots: Slots passed to the component.
  • context: 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 typing import NamedTuple
from django.template import Context
from django_components import Component, SlotInput

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

    class Kwargs(NamedTuple):
        size: int

    class Slots(NamedTuple):
        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(NamedTuple):
        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_template_name ¤

get_template_name(context: Context) -> Optional[str]

See source code

Filepath to the Django template associated with this component.

The filepath must be relative to either the file where the component class was defined, or one of the roots of STATIFILES_DIRS.

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

inject ¤

inject(key: str, default: Optional[Any] = 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.

on_render_after ¤

on_render_after(context: Context, template: Template, content: str) -> Optional[SlotResult]

See source code

Hook that runs just after the component's template was rendered. It receives the rendered output as the last argument.

You can use this hook to access the context or the template, but modifying them won't have any effect.

To override the content that gets rendered, you can return a string or SafeString from this hook.

on_render_before ¤

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

See source code

Hook that runs just before the component's template is rendered.

You can use this hook to access or modify the context or the template.

render classmethod ¤

render(
    context: Optional[Union[Dict[str, Any], Context]] = None,
    args: Optional[Any] = None,
    kwargs: Optional[Any] = None,
    slots: Optional[Any] = None,
    escape_slots_content: bool = True,
    deps_strategy: DependenciesStrategy = "document",
    type: Optional[DependenciesStrategy] = None,
    render_dependencies: bool = True,
    request: Optional[HttpRequest] = 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 *a, **kwa: "Click me!",
            "content3": Slot(lambda *a, **kwa: "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.
            icon = Icon.render(
                context=context,
                args=["icon-name"],
                deps_strategy="ignore",
            )
            # 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)
      • 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 with AJAX.
      • 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"
      • 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.

  • escape_slots_content - Optional. Whether the content from slots should be escaped with Django's escape. Defaults to True.

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 typing import NamedTuple, Optional
from django_components import Component, Slot, SlotInput

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

    class Kwargs(NamedTuple):
        surname: str
        age: int

    class Slots(NamedTuple):
        my_slot: Optional[SlotInput] = 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 *a, **kwa: "Click me!"),
    ),
)

render_to_response classmethod ¤

render_to_response(
    context: Optional[Union[Dict[str, Any], Context]] = None,
    args: Optional[Any] = None,
    kwargs: Optional[Any] = None,
    slots: Optional[Any] = None,
    escape_slots_content: bool = True,
    deps_strategy: DependenciesStrategy = "document",
    type: Optional[DependenciesStrategy] = None,
    render_dependencies: bool = True,
    request: Optional[HttpRequest] = 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)

ComponentCache ¤

Bases: django_components.extension.BaseExtensionClass

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"

Methods:

Attributes:

cache_name class-attribute instance-attribute ¤

cache_name: Optional[str] = None

See source code

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

enabled class-attribute instance-attribute ¤

enabled: bool = False

See source code

Whether this Component should be cached. Defaults to False.

ttl class-attribute instance-attribute ¤

ttl: Optional[int] = None

See source code

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.

get_cache ¤

get_cache() -> BaseCache

get_cache_key ¤

get_cache_key(args: List, kwargs: Dict, slots: Dict) -> str

get_entry ¤

get_entry(cache_key: str) -> Any

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.

set_entry ¤

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

ComponentDefaults ¤

Bases: django_components.extension.BaseExtensionClass

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 ¤

Bases: object

See source code

Base class for all extensions.

Read more on Extensions.

Methods:

Attributes:

ExtensionClass class-attribute instance-attribute ¤

ExtensionClass = BaseExtensionClass

See source code

Base class that the "extension class" 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 ExtensionClass. So it will be same as if the user had directly inherited from ExtensionClass. E.g.:

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

This setting decides what the extension class will inherit from.

class_name instance-attribute ¤

class_name: str

See source code

Name of the extension class.

By default, this is the same as name, 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
        ...

commands class-attribute instance-attribute ¤

commands: List[Type[ComponentCommand]] = []

See source code

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,
    ]

name instance-attribute ¤

name: str

See source code

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(),
        }

urls class-attribute instance-attribute ¤

urls: List[URLRoute] = []

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_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_input ¤

on_component_input(ctx: OnComponentInputContext) -> Optional[str]

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.

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"

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_rendered ¤

on_component_rendered(ctx: OnComponentRenderedContext) -> Optional[str]

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.

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

Example:

from django_components import ComponentExtension, OnComponentRenderedContext

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

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

ComponentFileEntry ¤

Bases: tuple

See source code

Result returned by get_component_files().

Attributes:

dot_path instance-attribute ¤

dot_path: str

See source code

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

filepath instance-attribute ¤

filepath: Path

See source code

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

ComponentInput dataclass ¤

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

Bases: object

See source code

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.

This class can be typed as:

Attributes:

args instance-attribute ¤

args: List

context instance-attribute ¤

context: Context

deps_strategy instance-attribute ¤

deps_strategy: DependenciesStrategy

kwargs instance-attribute ¤

kwargs: Dict

render_dependencies instance-attribute ¤

render_dependencies: bool

See source code

Deprecated. Instead use deps_strategy="ignore".

slots instance-attribute ¤

slots: Dict[SlotName, Slot]

type instance-attribute ¤

See source code

Deprecated alias for deps_strategy.

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 class-attribute instance-attribute ¤

See source code

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

Examples:

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

extend class-attribute instance-attribute ¤

extend: Union[bool, List[Type[Component]]] = True

See source code

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

js class-attribute instance-attribute ¤

See source code

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

Examples:

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

ComponentMediaInputPath module-attribute ¤

ComponentMediaInputPath = Union[str, bytes, SafeData, Path, PathLike, Callable[[], Union[str, bytes, SafeData, Path, PathLike]]]

See source code

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

If an entry is a SafeString (or has __html__ method), then entry is assumed to be a formatted HTML tag. Otherwise, it's assumed to be a path to a file.

Example:

class MyComponent
    class Media:
        js = [
            "path/to/script.js",
            b"script.js",
            SafeString("<script src='path/to/script.js'></script>"),
        ]
        css = [
            Path("path/to/style.css"),
            lambda: "path/to/style.css",
            lambda: Path("path/to/style.css"),
        ]

ComponentRegistry ¤

ComponentRegistry(
    library: Optional[Library] = None, settings: Optional[Union[RegistrySettings, Callable[[ComponentRegistry], RegistrySettings]]] = 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.

Parameters:

  • library (Library, default: None ) –

    Django Library associated with this registry. If omitted, the default Library instance from django_components is used.

  • settings (Union[RegistrySettings, Callable[[ComponentRegistry], RegistrySettings]], default: None ) –

    Configure 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.

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 %}
    

Methods:

Attributes:

library property ¤

library: Library

See source code

The template tag Library that is associated with the registry.

settings property ¤

settings: InternalRegistrySettings

See source code

Registry settings configured for this registry.

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()
# > {}

get ¤

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

See source code

Retrieve a Component class registered under the given name.

Parameters:

  • name (str) –

    The 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.

Parameters:

  • name (str) –

    The name under which the component was registered. Required.

Returns:

  • bool ( bool ) –

    True if the component is registered, False otherwise.

Example:

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

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 %}

Parameters:

  • name (str) –

    The name under which the component will be registered. Required.

  • component (Type[Component]) –

    The component class to register. Required.

Raises:

  • AlreadyRegistered if a different component was already registered under the same name.

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.

Parameters:

  • name (str) –

    The name under which the component is registered. Required.

Raises:

Example:

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

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 is_filled on this class is accessible inside the template as:

{{ component_vars.is_filled }}

Attributes:

is_filled instance-attribute ¤

is_filled: Dict[str, bool]

See source code

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.BaseExtensionClass, 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. 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!")

Component URL:

If the public attribute is set to True, the component will have its own URL that will point to the Component's View.

from django_components import Component

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

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

Will create a URL route like /components/ext/view/components/a1b2c3/.

To get the URL for the component, use get_component_url:

url = get_component_url(MyComponent)

Methods:

Attributes:

component class-attribute instance-attribute ¤

component = cast('Component', None)

See source code

The component instance.

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)

public class-attribute instance-attribute ¤

public = False

See source code

Whether the component should be available via a URL.

Example:

from django_components import Component

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

Will create a URL route like /components/ext/view/components/a1b2c3/.

To get the URL for the component, use get_component_url:

url = get_component_url(MyComponent)

url property ¤

url: str

See source code

The URL for the component.

Raises RuntimeError if the component is not public.

delete ¤

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

get ¤

get(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

patch ¤

patch(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

trace ¤

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

ComponentsSettings ¤

Bases: tuple

See source code

Settings available for django_components.

Example:

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

Attributes:

app_dirs class-attribute instance-attribute ¤

app_dirs: Optional[Sequence[str]] = None

See source code

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=[],
)

autodiscover class-attribute instance-attribute ¤

autodiscover: Optional[bool] = None

See source code

Toggle whether to run autodiscovery at the Django server startup.

Defaults to True

COMPONENTS = ComponentsSettings(
    autodiscover=False,
)

cache class-attribute instance-attribute ¤

cache: Optional[str] = None

See source code

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 class-attribute instance-attribute ¤

context_behavior: Optional[ContextBehaviorType] = None

See source code

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 change here.

debug_highlight_components class-attribute instance-attribute ¤

debug_highlight_components: Optional[bool] = None

See source code

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

Defaults to False.

COMPONENTS = ComponentsSettings(
    debug_highlight_components=True,
)

debug_highlight_slots class-attribute instance-attribute ¤

debug_highlight_slots: Optional[bool] = None

See source code

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

Defaults to False.

COMPONENTS = ComponentsSettings(
    debug_highlight_slots=True,
)

dirs class-attribute instance-attribute ¤

See source code

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=[],
)

dynamic_component_name class-attribute instance-attribute ¤

dynamic_component_name: Optional[str] = None

See source code

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 %}

extensions class-attribute instance-attribute ¤

See source code

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.
COMPONENTS = ComponentsSettings(
    extensions=[
        "path.to.my_extension.MyExtension",
        StorybookExtension,
    ],
)

forbidden_static_files class-attribute instance-attribute ¤

forbidden_static_files: Optional[List[Union[str, Pattern]]] = None

libraries class-attribute instance-attribute ¤

libraries: Optional[List[str]] = None

See source code

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 class-attribute instance-attribute ¤

multiline_tags: Optional[bool] = None

See source code

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_file_change class-attribute instance-attribute ¤

reload_on_file_change: Optional[bool] = None

See source code

This is relevant if you are using the project structure where HTML, JS, CSS and Python are in separate files and nested in a directory.

In this case you may notice that when you are running a development server, the server sometimes does not reload when you change component files.

Django's native live reload logic handles only Python files and HTML template files. It does NOT reload when other file types change or when template files are nested more than one level deep.

The setting reload_on_file_change fixes this, reloading the dev server even when your component's HTML, JS, or CSS changes.

If True, django_components configures Django to reload when files inside COMPONENTS.dirs or COMPONENTS.app_dirs change.

See Reload dev server on component file changes.

Defaults to False.

Warning

This setting should be enabled only for the dev environment!

reload_on_template_change class-attribute instance-attribute ¤

reload_on_template_change: Optional[bool] = None

static_files_allowed class-attribute instance-attribute ¤

static_files_allowed: Optional[List[Union[str, Pattern]]] = None

See source code

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.

static_files_forbidden class-attribute instance-attribute ¤

static_files_forbidden: Optional[List[Union[str, Pattern]]] = None

See source code

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 class-attribute instance-attribute ¤

tag_formatter: Optional[Union[TagFormatterABC, str]] = None

See source code

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

Examples:

  • "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 class-attribute instance-attribute ¤

template_cache_size: Optional[int] = None

See source code

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 ¤

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 class-attribute instance-attribute ¤

DJANGO = 'django'

See source code

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 class-attribute instance-attribute ¤

ISOLATED = 'isolated'

See source code

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 dataclass ¤

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 instance-attribute ¤

value: Callable[[], Any]

DependenciesStrategy module-attribute ¤

DependenciesStrategy = Literal['document', 'fragment', 'simple', 'prepend', 'append', 'ignore']

See source code

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

Read more about the dependencies strategies.

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.

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 class-attribute instance-attribute ¤

CONTEXT_BEHAVIOR: Optional[ContextBehaviorType] = None

See source code

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 class-attribute instance-attribute ¤

TAG_FORMATTER: Optional[Union[TagFormatterABC, str]] = None

See source code

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.

context_behavior class-attribute instance-attribute ¤

context_behavior: Optional[ContextBehaviorType] = None

See source code

Same as the global COMPONENTS.context_behavior setting, but for this registry.

If omitted, defaults to the global COMPONENTS.context_behavior setting.

tag_formatter class-attribute instance-attribute ¤

tag_formatter: Optional[Union[TagFormatterABC, str]] = None

See source code

Same as the global COMPONENTS.tag_formatter setting, but for this registry.

If omitted, defaults to the global COMPONENTS.tag_formatter setting.

Slot dataclass ¤

Slot(
    contents: Any,
    content_func: SlotFunc[TSlotData] = cast(SlotFunc[TSlotData], None),
    escaped: bool = False,
    component_name: Optional[str] = None,
    slot_name: Optional[str] = None,
    nodelist: Optional[NodeList] = None,
)

Bases: typing.Generic

See source code

This class holds the slot content function along with related metadata.

Attributes:

component_name class-attribute instance-attribute ¤

component_name: Optional[str] = None

See source code

Name of the component that originally defined or accepted this slot fill.

content_func class-attribute instance-attribute ¤

content_func: SlotFunc[TSlotData] = cast(SlotFunc[TSlotData], None)

contents instance-attribute ¤

contents: Any

See source code

The original value that was passed to the Slot constructor.

If the slot was defined with {% fill %} tag, this will be the raw string contents of the slot.

do_not_call_in_templates property ¤

do_not_call_in_templates: bool

escaped class-attribute instance-attribute ¤

escaped: bool = False

See source code

Whether the slot content has been escaped.

nodelist class-attribute instance-attribute ¤

nodelist: Optional[NodeList] = None

See source code

If the slot was defined with `{% fill %} tag, this will be the Nodelist of the slot content.

slot_name class-attribute instance-attribute ¤

slot_name: Optional[str] = None

See source code

Name of the slot that originally defined or accepted this slot fill.

SlotContent module-attribute ¤

SlotContent = SlotInput[TSlotData]

See source code

DEPRECATED: Use SlotInput instead. Will be removed in v1.

SlotFunc ¤

SlotInput module-attribute ¤

SlotInput = Union[SlotResult, SlotFunc[TSlotData], Slot[TSlotData]]

See source code

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 NamedTuple
from typing_extensions import TypedDict
from django_components import Component, SlotInput

class TableFooterSlotData(TypedDict):
    page_number: int

class Table(Component):
    class Slots(NamedTuple):
        header: SlotInput
        footer: SlotInput[TableFooterSlotData]

    template = "<div>{% slot 'footer' %}</div>"

SlotRef ¤

SlotRef(slot: SlotNode, context: Context)

Bases: object

See source code

SlotRef allows to treat a slot as a variable. The slot is rendered only once the instance is coerced to string.

This is used to access slots as variables inside the templates. When a SlotRef is rendered in the template with {{ my_lazy_slot }}, it will output the contents of the slot.

SlotResult module-attribute ¤

SlotResult = Union[str, SafeString]

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:

end_tag abstractmethod ¤

end_tag(name: str) -> str

See source code

Formats the end tag of a block component.

Parameters:

  • name (str) –

    Component's registered name. Required.

Returns:

  • str ( str ) –

    The formatted end tag.

parse abstractmethod ¤

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

Parameters:

  • tokens ([List(str]) –

    List of tokens passed to the component tag.

Returns:

  • TagResult ( 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'])

start_tag abstractmethod ¤

start_tag(name: str) -> str

See source code

Formats the start tag of a component.

Parameters:

  • name (str) –

    Component's registered name. Required.

Returns:

  • str ( str ) –

    The formatted start tag.

TagResult ¤

Bases: tuple

See source code

The return value from TagFormatter.parse().

Read more about Tag formatter.

Attributes:

component_name instance-attribute ¤

component_name: str

See source code

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 instance-attribute ¤

tokens: List[str]

See source code

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: Optional[Callable[[str], str]] = 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.

Parameters:

  • map_module (Callable[[str], str], default: None ) –

    Map the module paths with map_module function. This serves as an escape hatch for when you need to use this function in tests.

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: Optional[Type[Template]] = None,
    origin: Optional[Origin] = None,
    name: Optional[str] = None,
    engine: Optional[Any] = None,
) -> Template

See source code

Create a Template instance that will be cached as per the COMPONENTS.template_cache_size setting.

Parameters:

  • template_string (str) –

    Template as a string, same as the first argument to Django's Template. Required.

  • template_cls (Type[Template], default: None ) –

    Specify the Template class that should be instantiated. Defaults to Django's Template class.

  • origin (Type[Origin], default: None ) –
  • name (Type[str], default: None ) –

    Sets Template.name

  • engine (Type[Any], default: None ) –

    Sets Template.engine

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=...
)

format_attributes ¤

format_attributes(attributes: Mapping[str, Any]) -> str

See source code

Format a dict of attributes into an HTML attributes string.

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_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.

Parameters:

  • include_apps (bool, default: True ) –

    Include directories from installed Django apps. Defaults to 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: Optional[str] = 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.

Parameters:

  • suffix (Optional[str], default: None ) –

    The suffix to search for. E.g. .py, .js, .css. Defaults to None, which will search for all files.

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: Union[Type[Component], Component], query: Optional[Dict] = None, fragment: Optional[str] = None) -> str

See source code

Get the URL for a Component.

Raises RuntimeError if the component is not public.

Read more about Component views and URLs.

get_component_url() optionally accepts query and fragment arguments.

Example:

from django_components import Component, get_component_url

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

# Get the URL for the component
url = get_component_url(
    MyComponent,
    query={"foo": "bar"},
    fragment="baz",
)
# /components/ext/view/components/c1ab2c3?foo=bar#baz

import_libraries ¤

import_libraries(map_module: Optional[Callable[[str], str]] = None) -> List[str]

See source code

Import modules set in COMPONENTS.libraries setting.

See Autodiscovery.

Parameters:

  • map_module (Callable[[str], str], default: None ) –

    Map the module paths with map_module function. This serves as an escape hatch for when you need to use this function in tests.

Returns:

  • List[str] –

    List[str]: A list of module paths of imported files.

Examples:

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: Optional[ComponentRegistry] = None) -> Callable[[Type[TComponent]], Type[TComponent]]

See source code

Class decorator for registering a component to a component registry.

See Registering components.

Parameters:

  • name (str) –

    Registered name. This is the name by which the component will be accessed from within a template when using the {% component %} tag. Required.

  • registry (ComponentRegistry, default: None ) –

    Specify the registry to which to register this component. If omitted, component is registered to the default registry.

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 module-attribute ¤

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 a string that contains parts that were rendered by components, this function inserts all used JS and CSS.

By default, the string is parsed as an HTML and: - CSS is inserted at the end of <head> (if present) - JS is inserted at the end of <body> (if present)

If you used {% component_js_dependencies %} or {% component_css_dependencies %}, then the JS and CSS will be inserted only at these locations.

Example:

def my_view(request):
    template = Template('''
        {% load components %}
        <!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: Optional[str] = None, allowed_flags: Optional[List[str]] = 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().