django_components ¤
Main package for Django Components.
app_settings ¤
ContextBehavior ¤
DJANGO class-attribute
instance-attribute
¤
With this setting, component fills behave as usual Django tags. That is, they enrich the context, and pass it along.
- Component fills use the context of the component they are within.
- Variables from
get_context_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 get_context_data()
method
Then if component "my_comp" defines context
Then this will render:
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
¤
This setting makes the component fills behave similar to Vue or React, where the fills use EXCLUSIVELY the context variables defined in get_context_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_context_data()
method
Then if component "my_comp" defines context
Then this will render:
Because both variables "my_var" and "cheese" are taken from the root context. Since "cheese" is not defined in root context, it's empty.
attributes ¤
append_attributes ¤
Merges the key-value pairs and returns a new dictionary.
If a key is present multiple times, its values are concatenated with a space character as separator in the final dictionary.
Source code in src/django_components/attributes.py
attributes_to_string ¤
Convert a dict of attributes to a string.
Source code in src/django_components/attributes.py
autodiscover ¤
autodiscover ¤
Search for component files and import them. Returns a list of module paths of imported files.
Autodiscover searches in the locations as defined by Loader.get_dirs
.
You can map the module paths with map_module
function. This serves as an escape hatch for when you need to use this function in tests.
Source code in src/django_components/autodiscover.py
import_libraries ¤
Import modules set in COMPONENTS.libraries
setting.
You can map the module paths with map_module
function. This serves as an escape hatch for when you need to use this function in tests.
Source code in src/django_components/autodiscover.py
search_dirs ¤
Search the directories for the given glob pattern. Glob search results are returned as a flattened list.
Source code in src/django_components/autodiscover.py
component ¤
Component ¤
Component(
registered_name: Optional[str] = None,
component_id: Optional[str] = None,
outer_context: Optional[Context] = None,
fill_content: Optional[Dict[str, FillContent]] = None,
registry: Optional[ComponentRegistry] = None,
)
Bases: Generic[ArgsType, KwargsType, DataType, SlotsType]
Source code in src/django_components/component.py
Media class-attribute
instance-attribute
¤
Media = ComponentMediaInput
Defines JS and CSS media files associated with this component.
css class-attribute
instance-attribute
¤
Inlined CSS associated with this component.
input property
¤
Input holds the data (like arg, kwargs, slots) that were passsed to the current execution of the render
method.
is_filled property
¤
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.
js class-attribute
instance-attribute
¤
Inlined JS associated with this component.
media instance-attribute
¤
media: Media
Normalized definition of JS and CSS media files associated with this component.
NOTE: This field is generated from Component.Media class.
response_class class-attribute
instance-attribute
¤
response_class = HttpResponse
This allows to configure what class is used to generate response from render_to_response
template class-attribute
instance-attribute
¤
Inlined Django template associated with this component. Can be a plain string or a Template instance.
Only one of template_name
, get_template_name
, template
or get_template
must be defined.
template_name class-attribute
instance-attribute
¤
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_name
, get_template_name
, template
or get_template
must be defined.
as_view classmethod
¤
as_view(**initkwargs: Any) -> ViewFn
Shortcut for calling Component.View.as_view
and passing component instance to it.
Source code in src/django_components/component.py
get_template ¤
Inlined Django template associated with this component. Can be a plain string or a Template instance.
Only one of template_name
, get_template_name
, template
or get_template
must be defined.
Source code in src/django_components/component.py
get_template_name ¤
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_name
, get_template_name
, template
or get_template
must be defined.
Source code in src/django_components/component.py
inject ¤
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 mut be used inside the get_context_data()
method and raises an error if called elsewhere.
Example:
Given this template:
{% provide "provider" hello="world" %}
{% component "my_comp" %}
{% endcomponent %}
{% endprovide %}
And given this definition of "my_comp" component:
from django_components import Component, register
@register("my_comp")
class MyComp(Component):
template = "hi {{ data.hello }}!"
def get_context_data(self):
data = self.inject("provider")
return {"data": data}
This renders into:
As the {{ data.hello }}
is taken from the "provider".
Source code in src/django_components/component.py
on_render_after ¤
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.
Source code in src/django_components/component.py
on_render_before ¤
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[ArgsType] = None,
kwargs: Optional[KwargsType] = None,
slots: Optional[SlotsType] = None,
escape_slots_content: bool = True,
) -> str
Render the component into a string.
Inputs: - args
- Positional args for the component. This is the same as calling the component as {% component "my_comp" arg1 arg2 ... %}
- kwargs
- Kwargs for the component. This is the same as calling the component as {% component "my_comp" key1=val1 key2=val2 ... %}
- slots
- Component slot fills. This is the same as pasing {% fill %}
tags to the component. Accepts a dictionary of { slot_name: slot_content }
where slot_content
can be a string or render function. - escape_slots_content
- Whether the content from slots
should be escaped. - context
- A context (dictionary or Django's Context) within which the component is rendered. The keys on the context can be accessed from within the template. - NOTE: In "isolated" mode, context is NOT accessible, and data MUST be passed via component's args and kwargs.
Example:
MyComponent.render(
args=[1, "two", {}],
kwargs={
"key": 123,
},
slots={
"header": 'STATIC TEXT HERE',
"footer": lambda ctx, slot_kwargs, slot_ref: f'CTX: {ctx['hello']} SLOT_DATA: {slot_kwargs['abc']}',
},
escape_slots_content=False,
)
Source code in src/django_components/component.py
render_css_dependencies ¤
render_css_dependencies() -> SafeString
Render only CSS dependencies available in the media class or provided as a string.
Source code in src/django_components/component.py
render_dependencies ¤
render_dependencies() -> SafeString
Helper function to render all dependencies for a component.
Source code in src/django_components/component.py
render_js_dependencies ¤
render_js_dependencies() -> SafeString
Render only JS dependencies available in the media class or provided as a string.
Source code in src/django_components/component.py
render_to_response classmethod
¤
render_to_response(
context: Optional[Union[Dict[str, Any], Context]] = None,
slots: Optional[SlotsType] = None,
escape_slots_content: bool = True,
args: Optional[ArgsType] = None,
kwargs: Optional[KwargsType] = None,
*response_args: Any,
**response_kwargs: Any
) -> HttpResponse
Render the component and wrap the content in the response class.
The response class is taken from Component.response_class
. Defaults to django.http.HttpResponse
.
This is the interface for the django.views.View
class which allows us to use components as Django views with component.as_view()
.
Inputs: - args
- Positional args for the component. This is the same as calling the component as {% component "my_comp" arg1 arg2 ... %}
- kwargs
- Kwargs for the component. This is the same as calling the component as {% component "my_comp" key1=val1 key2=val2 ... %}
- slots
- Component slot fills. This is the same as pasing {% fill %}
tags to the component. Accepts a dictionary of { slot_name: slot_content }
where slot_content
can be a string or render function. - escape_slots_content
- Whether the content from slots
should be escaped. - context
- A context (dictionary or Django's Context) within which the component is rendered. The keys on the context can be accessed from within the template. - NOTE: In "isolated" mode, context is NOT accessible, and data MUST be passed via component's args and kwargs.
Any additional args and kwargs are passed to the response_class
.
Example:
MyComponent.render_to_response(
args=[1, "two", {}],
kwargs={
"key": 123,
},
slots={
"header": 'STATIC TEXT HERE',
"footer": lambda ctx, slot_kwargs, slot_ref: f'CTX: {ctx['hello']} SLOT_DATA: {slot_kwargs['abc']}',
},
escape_slots_content=False,
# HttpResponse input
status=201,
headers={...},
)
# HttpResponse(content=..., status=201, headers=...)
Source code in src/django_components/component.py
ComponentNode ¤
ComponentNode(
name: str,
args: List[Expression],
kwargs: RuntimeKwargs,
registry: ComponentRegistry,
isolated_context: bool = False,
fill_nodes: Optional[List[FillNode]] = None,
node_id: Optional[str] = None,
)
Bases: BaseNode
Django.template.Node subclass that renders a django-components component
Source code in src/django_components/component.py
ComponentView ¤
component_media ¤
ComponentMediaInput ¤
Defines JS and CSS media files associated with this component.
MediaMeta ¤
Bases: MediaDefiningClass
Metaclass for handling media files for components.
Similar to MediaDefiningClass
, this class supports the use of Media
attribute to define associated JS/CSS files, which are then available under media
attribute as a instance of Media
class.
This subclass has following changes:
1. Support for multiple interfaces of JS/CSS¤
-
As plain strings
-
As lists
-
[CSS ONLY] Dicts of strings
-
[CSS ONLY] Dicts of lists
2. Media are first resolved relative to class definition file¤
E.g. if in a directory my_comp
you have script.js
and my_comp.py
, and my_comp.py
looks like this:
Then script.js
will be resolved as my_comp/script.js
.
3. Media can be defined as str, bytes, PathLike, SafeString, or function of thereof¤
E.g.:
def lazy_eval_css():
# do something
return path
class MyComponent(Component):
class Media:
js = b"script.js"
css = lazy_eval_css
4. Subclass Media
class with media_class
¤
Normal MediaDefiningClass
creates an instance of Media
class under the media
attribute. This class allows to override which class will be instantiated with media_class
attribute:
class MyMedia(Media):
def render_js(self):
...
class MyComponent(Component):
media_class = MyMedia
def get_context_data(self):
assert isinstance(self.media, MyMedia)
component_registry ¤
registry module-attribute
¤
registry: ComponentRegistry = ComponentRegistry()
The default and global component registry. Use this instance to directly register or remove components:
ComponentRegistry ¤
ComponentRegistry(
library: Optional[Library] = None, settings: Optional[Union[RegistrySettings, Callable[[ComponentRegistry], RegistrySettings]]] = None
)
Manages which components can be used in the template tags.
Each ComponentRegistry instance is associated with an instance of Django's Library. So when you register or unregister a component to/from a component registry, behind the scenes the registry automatically adds/removes the component's template tag to/from the Library.
The Library instance can be set at instantiation. If omitted, then the default Library instance from django_components is used. The Library instance can be accessed under library
attribute.
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()
Source code in src/django_components/component_registry.py
library property
¤
The template tag library with which the component registry is associated.
all ¤
Retrieve all registered component classes.
Example:
# First register components
registry.register("button", ButtonComponent)
registry.register("card", CardComponent)
# Then get all
registry.all()
# > {
# > "button": ButtonComponent,
# > "card": CardComponent,
# > }
Source code in src/django_components/component_registry.py
clear ¤
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()
# > {}
Source code in src/django_components/component_registry.py
get ¤
Retrieve a component class registered under the given name.
Raises NotRegistered
if the given name is not registered.
Example:
# First register component
registry.register("button", ButtonComponent)
# Then get
registry.get("button")
# > ButtonComponent
Source code in src/django_components/component_registry.py
register ¤
Register a component with this registry under the given name.
A component MUST be registered before it can be used in a template such as:
Raises AlreadyRegistered
if a different component was already registered under the same name.
Example:
Source code in src/django_components/component_registry.py
unregister ¤
unregister(name: str) -> None
Unlinks a previously-registered component from the registry under the given name.
Once a component is unregistered, it CANNOT be used in a template anymore. Following would raise an error:
Raises NotRegistered
if the given name is not registered.
Example:
# First register component
registry.register("button", ButtonComponent)
# Then unregister
registry.unregister("button")
Source code in src/django_components/component_registry.py
register ¤
register(name: str, registry: Optional[ComponentRegistry] = None) -> Callable[[_TComp], _TComp]
Class decorator to register a component.
Usage:
Optionally specify which ComponentRegistry
the component should be registered to by setting the registry
kwarg:
my_lib = django.template.Library()
my_reg = ComponentRegistry(library=my_lib)
@register("my_component", registry=my_reg)
class MyComponent(Component):
...
Source code in src/django_components/component_registry.py
components ¤
dynamic ¤
DynamicComponent ¤
DynamicComponent(
registered_name: Optional[str] = None,
component_id: Optional[str] = None,
outer_context: Optional[Context] = None,
fill_content: Optional[Dict[str, FillContent]] = None,
registry: Optional[ComponentRegistry] = None,
)
Bases: Component
Dynamic component - This component takes inputs and renders the outputs depending on the is
and registry
arguments.
-
is
- required - The component class or registered name of the component that will be rendered in this place. -
registry
- optional - Specify the registry to search for the registered name. If omitted, all registries are searched.
Source code in src/django_components/component.py
Media class-attribute
instance-attribute
¤
Media = ComponentMediaInput
Defines JS and CSS media files associated with this component.
css class-attribute
instance-attribute
¤
Inlined CSS associated with this component.
input property
¤
Input holds the data (like arg, kwargs, slots) that were passsed to the current execution of the render
method.
is_filled property
¤
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.
js class-attribute
instance-attribute
¤
Inlined JS associated with this component.
media instance-attribute
¤
media: Media
Normalized definition of JS and CSS media files associated with this component.
NOTE: This field is generated from Component.Media class.
response_class class-attribute
instance-attribute
¤
response_class = HttpResponse
This allows to configure what class is used to generate response from render_to_response
template_name class-attribute
instance-attribute
¤
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_name
, get_template_name
, template
or get_template
must be defined.
as_view classmethod
¤
as_view(**initkwargs: Any) -> ViewFn
Shortcut for calling Component.View.as_view
and passing component instance to it.
Source code in src/django_components/component.py
get_template ¤
Inlined Django template associated with this component. Can be a plain string or a Template instance.
Only one of template_name
, get_template_name
, template
or get_template
must be defined.
Source code in src/django_components/component.py
get_template_name ¤
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_name
, get_template_name
, template
or get_template
must be defined.
Source code in src/django_components/component.py
inject ¤
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 mut be used inside the get_context_data()
method and raises an error if called elsewhere.
Example:
Given this template:
{% provide "provider" hello="world" %}
{% component "my_comp" %}
{% endcomponent %}
{% endprovide %}
And given this definition of "my_comp" component:
from django_components import Component, register
@register("my_comp")
class MyComp(Component):
template = "hi {{ data.hello }}!"
def get_context_data(self):
data = self.inject("provider")
return {"data": data}
This renders into:
As the {{ data.hello }}
is taken from the "provider".
Source code in src/django_components/component.py
on_render_after ¤
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.
Source code in src/django_components/component.py
on_render_before ¤
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[ArgsType] = None,
kwargs: Optional[KwargsType] = None,
slots: Optional[SlotsType] = None,
escape_slots_content: bool = True,
) -> str
Render the component into a string.
Inputs: - args
- Positional args for the component. This is the same as calling the component as {% component "my_comp" arg1 arg2 ... %}
- kwargs
- Kwargs for the component. This is the same as calling the component as {% component "my_comp" key1=val1 key2=val2 ... %}
- slots
- Component slot fills. This is the same as pasing {% fill %}
tags to the component. Accepts a dictionary of { slot_name: slot_content }
where slot_content
can be a string or render function. - escape_slots_content
- Whether the content from slots
should be escaped. - context
- A context (dictionary or Django's Context) within which the component is rendered. The keys on the context can be accessed from within the template. - NOTE: In "isolated" mode, context is NOT accessible, and data MUST be passed via component's args and kwargs.
Example:
MyComponent.render(
args=[1, "two", {}],
kwargs={
"key": 123,
},
slots={
"header": 'STATIC TEXT HERE',
"footer": lambda ctx, slot_kwargs, slot_ref: f'CTX: {ctx['hello']} SLOT_DATA: {slot_kwargs['abc']}',
},
escape_slots_content=False,
)
Source code in src/django_components/component.py
render_css_dependencies ¤
render_css_dependencies() -> SafeString
Render only CSS dependencies available in the media class or provided as a string.
Source code in src/django_components/component.py
render_dependencies ¤
render_dependencies() -> SafeString
Helper function to render all dependencies for a component.
Source code in src/django_components/component.py
render_js_dependencies ¤
render_js_dependencies() -> SafeString
Render only JS dependencies available in the media class or provided as a string.
Source code in src/django_components/component.py
render_to_response classmethod
¤
render_to_response(
context: Optional[Union[Dict[str, Any], Context]] = None,
slots: Optional[SlotsType] = None,
escape_slots_content: bool = True,
args: Optional[ArgsType] = None,
kwargs: Optional[KwargsType] = None,
*response_args: Any,
**response_kwargs: Any
) -> HttpResponse
Render the component and wrap the content in the response class.
The response class is taken from Component.response_class
. Defaults to django.http.HttpResponse
.
This is the interface for the django.views.View
class which allows us to use components as Django views with component.as_view()
.
Inputs: - args
- Positional args for the component. This is the same as calling the component as {% component "my_comp" arg1 arg2 ... %}
- kwargs
- Kwargs for the component. This is the same as calling the component as {% component "my_comp" key1=val1 key2=val2 ... %}
- slots
- Component slot fills. This is the same as pasing {% fill %}
tags to the component. Accepts a dictionary of { slot_name: slot_content }
where slot_content
can be a string or render function. - escape_slots_content
- Whether the content from slots
should be escaped. - context
- A context (dictionary or Django's Context) within which the component is rendered. The keys on the context can be accessed from within the template. - NOTE: In "isolated" mode, context is NOT accessible, and data MUST be passed via component's args and kwargs.
Any additional args and kwargs are passed to the response_class
.
Example:
MyComponent.render_to_response(
args=[1, "two", {}],
kwargs={
"key": 123,
},
slots={
"header": 'STATIC TEXT HERE',
"footer": lambda ctx, slot_kwargs, slot_ref: f'CTX: {ctx['hello']} SLOT_DATA: {slot_kwargs['abc']}',
},
escape_slots_content=False,
# HttpResponse input
status=201,
headers={...},
)
# HttpResponse(content=..., status=201, headers=...)
Source code in src/django_components/component.py
context ¤
This file centralizes various ways we use Django's Context class pass data across components, nodes, slots, and contexts.
You can think of the Context as our storage system.
copy_forloop_context ¤
Forward the info about the current loop
Source code in src/django_components/context.py
get_injected_context_var ¤
get_injected_context_var(component_name: str, context: Context, key: str, default: Optional[Any] = None) -> Any
Retrieve a 'provided' field. The field MUST have been previously 'provided' by the component's ancestors using the {% provide %}
template tag.
Source code in src/django_components/context.py
prepare_context ¤
Initialize the internal context state.
Source code in src/django_components/context.py
set_component_id ¤
We use the Context object to pass down info on inside of which component we are currently rendering.
set_provided_context_var ¤
'Provide' given data under given key. In other words, this data can be retrieved using self.inject(key)
inside of get_context_data()
method of components that are nested inside the {% provide %}
tag.
Source code in src/django_components/context.py
expression ¤
Operator ¤
Bases: ABC
Operator describes something that somehow changes the inputs to template tags (the {% %}
).
For example, a SpreadOperator inserts one or more kwargs at the specified location.
SpreadOperator ¤
process_aggregate_kwargs ¤
This function aggregates "prefixed" kwargs into dicts. "Prefixed" kwargs start with some prefix delimited with :
(e.g. attrs:
).
Example:
process_component_kwargs({"abc:one": 1, "abc:two": 2, "def:three": 3, "four": 4})
# {"abc": {"one": 1, "two": 2}, "def": {"three": 3}, "four": 4}
We want to support a use case similar to Vue's fallthrough attributes. In other words, where a component author can designate a prop (input) which is a dict and which will be rendered as HTML attributes.
This is useful for allowing component users to tweak styling or add event handling to the underlying HTML. E.g.:
class="pa-4 d-flex text-black"
or @click.stop="alert('clicked!')"
So if the prop is attrs
, and the component is called like so:
then, if attrs
is:
and the component template is:
Then this renders:
However, this way it is difficult for the component user to define the attrs
variable, especially if they want to combine static and dynamic values. Because they will need to pre-process the attrs
dict.
So, instead, we allow to "aggregate" props into a dict. So all props that start with attrs:
, like attrs:class="text-red"
, will be collected into a dict at key attrs
.
This provides sufficient flexiblity to make it easy for component users to provide "fallthrough attributes", and sufficiently easy for component authors to process that input while still being able to provide their own keys.
Source code in src/django_components/expression.py
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
|
finders ¤
ComponentsFileSystemFinder ¤
Bases: BaseFinder
A static files finder based on FileSystemFinder
.
Differences: - This finder uses COMPONENTS.dirs
setting to locate files instead of STATICFILES_DIRS
. - Whether a file within COMPONENTS.dirs
is considered a STATIC file is configured by COMPONENTS.static_files_allowed
and COMPONENTS.forbidden_static_files
. - If COMPONENTS.dirs
is not set, defaults to settings.BASE_DIR / "components"
Source code in src/django_components/finders.py
find ¤
Look for files in the extra locations as defined in COMPONENTS.dirs.
Source code in src/django_components/finders.py
find_location ¤
Find a requested static file in a location and return the found absolute path (or None
if no match).
Source code in src/django_components/finders.py
list ¤
List all files in all locations.
Source code in src/django_components/finders.py
library ¤
Module for interfacing with Django's Library (django.template.library
)
PROTECTED_TAGS module-attribute
¤
PROTECTED_TAGS = [
"component_dependencies",
"component_css_dependencies",
"component_js_dependencies",
"fill",
"html_attrs",
"provide",
"slot",
]
These are the names that users cannot choose for their components, as they would conflict with other tags in the Library.
logger ¤
trace ¤
TRACE level logger.
To display TRACE logs, set the logging level to 5.
Example:
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"console": {
"class": "logging.StreamHandler",
"stream": sys.stdout,
},
},
"loggers": {
"django_components": {
"level": 5,
"handlers": ["console"],
},
},
}
Source code in src/django_components/logger.py
trace_msg ¤
trace_msg(
action: Literal["PARSE", "ASSOC", "RENDR", "GET", "SET"],
node_type: Literal["COMP", "FILL", "SLOT", "PROVIDE", "N/A"],
node_name: str,
node_id: str,
msg: str = "",
component_id: Optional[str] = None,
) -> None
TRACE level logger with opinionated format for tracing interaction of components, nodes, and slots. Formats messages like so:
"ASSOC SLOT test_slot ID 0088 TO COMP 0087"
Source code in src/django_components/logger.py
middleware ¤
ComponentDependencyMiddleware ¤
ComponentDependencyMiddleware(get_response: Callable[[HttpRequest], HttpResponse])
Middleware that inserts CSS/JS dependencies for all rendered components at points marked with template tags.
Source code in src/django_components/middleware.py
DependencyReplacer ¤
Replacer for use in re.sub that replaces the first placeholder CSS and JS tags it encounters and removes any subsequent ones.
Source code in src/django_components/middleware.py
join_media ¤
Return combined media object for iterable of components.
node ¤
BaseNode ¤
BaseNode(
nodelist: Optional[NodeList] = None,
node_id: Optional[str] = None,
args: Optional[List[Expression]] = None,
kwargs: Optional[RuntimeKwargs] = None,
)
Bases: Node
Shared behavior for our subclasses of Django's Node
Source code in src/django_components/node.py
get_node_children ¤
Get child Nodes from Node's nodelist atribute.
This function is taken from get_nodes_by_type
method of django.template.base.Node
.
Source code in src/django_components/node.py
get_template_for_include_node ¤
This snippet is taken directly from IncludeNode.render()
. Unfortunately the render logic doesn't separate out template loading logic from rendering, so we have to copy the method.
Source code in src/django_components/node.py
walk_nodelist ¤
walk_nodelist(nodes: NodeList, callback: Callable[[Node], Optional[str]], context: Optional[Context] = None) -> None
Recursively walk a NodeList, calling callback
for each Node.
Source code in src/django_components/node.py
provide ¤
ProvideNode ¤
ProvideNode(nodelist: NodeList, trace_id: str, node_id: Optional[str] = None, kwargs: Optional[RuntimeKwargs] = None)
Bases: BaseNode
Implementation of the {% provide %}
tag. For more info see Component.inject
.
Source code in src/django_components/provide.py
slots ¤
FillContent dataclass
¤
FillContent(content_func: SlotFunc[TSlotData], slot_default_var: Optional[SlotDefaultName], slot_data_var: Optional[SlotDataName])
Bases: Generic[TSlotData]
This represents content set with the {% fill %}
tag, e.g.:
{% component "my_comp" %}
{% fill "first_slot" %} <--- This
hi
{{ my_var }}
hello
{% endfill %}
{% endcomponent %}
FillNode ¤
FillNode(nodelist: NodeList, kwargs: RuntimeKwargs, trace_id: str, node_id: Optional[str] = None, is_implicit: bool = False)
Bases: BaseNode
Set when a component
tag pair is passed template content that excludes fill
tags. Nodes of this type contribute their nodelists to slots marked as 'default'.
Source code in src/django_components/slots.py
Slot ¤
SlotFill dataclass
¤
SlotFill(
name: str,
escaped_name: str,
is_filled: bool,
content_func: SlotFunc[TSlotData],
slot_default_var: Optional[SlotDefaultName],
slot_data_var: Optional[SlotDataName],
)
Bases: Generic[TSlotData]
SlotFill describes what WILL be rendered.
It is a Slot that has been resolved against FillContents passed to a Component.
SlotNode ¤
SlotNode(
nodelist: NodeList,
trace_id: str,
node_id: Optional[str] = None,
kwargs: Optional[RuntimeKwargs] = None,
is_required: bool = False,
is_default: bool = False,
)
Bases: BaseNode
Source code in src/django_components/slots.py
SlotRef ¤
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.
Source code in src/django_components/slots.py
parse_slot_fill_nodes_from_component_nodelist ¤
parse_slot_fill_nodes_from_component_nodelist(nodes: Tuple[Node, ...], ignored_nodes: Tuple[Type[Node]]) -> List[FillNode]
Given a component body (django.template.NodeList
), find all slot fills, whether defined explicitly with {% fill %}
or implicitly.
So if we have a component body:
{% component "mycomponent" %}
{% fill "first_fill" %}
Hello!
{% endfill %}
{% fill "second_fill" %}
Hello too!
{% endfill %}
{% endcomponent %}
django.template.Node
) for fill "first_fill"
and fill "second_fill"
. Source code in src/django_components/slots.py
resolve_slots ¤
resolve_slots(
context: Context,
template: Template,
component_name: Optional[str],
fill_content: Dict[SlotName, FillContent],
is_dynamic_component: bool = False,
) -> Tuple[Dict[SlotId, Slot], Dict[SlotId, SlotFill]]
Search the template for all SlotNodes, and associate the slots with the given fills.
Returns tuple of: - Slots defined in the component's Template with {% slot %}
tag - SlotFills (AKA slots matched with fills) describing what will be rendered for each slot.
Source code in src/django_components/slots.py
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 |
|
tag_formatter ¤
ComponentFormatter ¤
ComponentFormatter(tag: str)
Bases: TagFormatterABC
The original django_component's component tag formatter, it uses the component
and endcomponent
tags, and the component name is gives as the first positional arg.
Example as block:
Example as inlined tag:
Source code in src/django_components/tag_formatter.py
InternalTagFormatter ¤
InternalTagFormatter(tag_formatter: TagFormatterABC)
ShorthandComponentFormatter ¤
Bases: TagFormatterABC
The component tag formatter that uses <name>
/ end<name>
tags.
This is similar to django-web-components and django-slippers syntax.
Example as block:
Example as inlined tag:
TagFormatterABC ¤
Bases: ABC
end_tag abstractmethod
¤
parse abstractmethod
¤
Given the tokens (words) of 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)
.
Example:
Given a component declarations:
{% component "my_comp" key=val key2=val2 %}
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. And we pass remaining tokens unmodified, as that's the input to the component.
So in the end, we return a tuple:
('my_comp', ['key=val', 'key2=val2'])
Source code in src/django_components/tag_formatter.py
TagResult ¤
get_tag_formatter ¤
get_tag_formatter(registry: ComponentRegistry) -> InternalTagFormatter
Returns an instance of the currently configured component tag formatter.
Source code in src/django_components/tag_formatter.py
template ¤
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
Create a Template instance that will be cached as per the TEMPLATE_CACHE_SIZE
setting.
Source code in src/django_components/template.py
template_loader ¤
Template loader that loads templates from each Django app's "components" directory.
Loader ¤
Bases: Loader
get_dirs ¤
Prepare directories that may contain component files:
Searches for dirs set in COMPONENTS.dirs
settings. If none set, defaults to searching for a "components" app. The dirs in COMPONENTS.dirs
must be absolute paths.
In addition to that, also all apps are checked for [app]/components
dirs.
Paths are accepted only if they resolve to a directory. E.g. /path/to/django_project/my_app/components/
.
BASE_DIR
setting is required.
Source code in src/django_components/template_loader.py
get_dirs ¤
Helper for using django_component's FilesystemLoader class to obtain a list of directories where component python files may be defined.
Source code in src/django_components/template_loader.py
template_parser ¤
Overrides for the Django Template system to allow finer control over template parsing.
Based on Django Slippers v0.6.2 - https://github.com/mixxorz/slippers/blob/main/slippers/template.py
parse_bits ¤
parse_bits(
parser: Parser, bits: List[str], params: List[str], name: str
) -> Tuple[List[FilterExpression], List[Tuple[str, FilterExpression]]]
Parse bits for template tag helpers simple_tag and inclusion_tag, in particular by detecting syntax errors and by extracting positional and keyword arguments.
This is a simplified version of django.template.library.parse_bits
where we use custom regex to handle special characters in keyword names.
Furthermore, our version allows duplicate keys, and instead of return kwargs as a dict, we return it as a list of key-value pairs. So it is up to the user of this function to decide whether they support duplicate keys or not.
Source code in src/django_components/template_parser.py
token_kwargs ¤
Parse token keyword arguments and return a dictionary of the arguments retrieved from the bits
token list.
bits
is a list containing the remainder of the token (split by spaces) that is to be checked for arguments. Valid arguments are removed from this list.
There is no requirement for all remaining token bits
to be keyword arguments, so return the dictionary as soon as an invalid argument format is reached.
Source code in src/django_components/template_parser.py
templatetags ¤
component_tags ¤
component ¤
component(parser: Parser, token: Token, registry: ComponentRegistry, tag_name: str) -> ComponentNode
To give the component access to the template context
{% component "name" positional_arg keyword_arg=value ... %}
To render the component in an isolated context
{% component "name" positional_arg keyword_arg=value ... only %}
Positional and keyword arguments can be literals or template variables. The component name must be a single- or double-quotes string and must be either the first positional argument or, if there are no positional arguments, passed as 'name'.
Source code in src/django_components/templatetags/component_tags.py
component_css_dependencies ¤
component_css_dependencies(preload: str = '') -> SafeString
Marks location where CSS link tags should be rendered.
Source code in src/django_components/templatetags/component_tags.py
component_dependencies ¤
component_dependencies(preload: str = '') -> SafeString
Marks location where CSS link and JS script tags should be rendered.
Source code in src/django_components/templatetags/component_tags.py
component_js_dependencies ¤
component_js_dependencies(preload: str = '') -> SafeString
Marks location where JS script tags should be rendered.
Source code in src/django_components/templatetags/component_tags.py
fill ¤
fill(parser: Parser, token: Token) -> FillNode
Block tag whose contents 'fill' (are inserted into) an identically named 'slot'-block in the component template referred to by a parent component. It exists to make component nesting easier.
This tag is available only within a {% component %}..{% endcomponent %} block. Runtime checks should prohibit other usages.
Source code in src/django_components/templatetags/component_tags.py
html_attrs ¤
This tag takes: - Optional dictionary of attributes (attrs
) - Optional dictionary of defaults (defaults
) - Additional kwargs that are appended to the former two
The inputs are merged and resulting dict is rendered as HTML attributes (key="value"
).
Rules: 1. Both attrs
and defaults
can be passed as positional args or as kwargs 2. Both attrs
and defaults
are optional (can be omitted) 3. Both attrs
and defaults
are dictionaries, and we can define them the same way we define dictionaries for the component
tag. So either as attrs=attrs
or attrs:key=value
. 4. All other kwargs (key=value
) are appended and can be repeated.
Normal kwargs (key=value
) are concatenated to existing keys. So if e.g. key "class" is supplied with value "my-class", then adding class="extra-class"
will result in `class="my-class extra-class".
Example:
Source code in src/django_components/templatetags/component_tags.py
types ¤
Helper types for IDEs.
utils ¤
gen_id ¤
Generate a unique ID that can be associated with a Node
lazy_cache ¤
Decorator that caches the given function similarly to functools.lru_cache
. But the cache is instantiated only at first invocation.
cache
argument is a function that generates the cache function, e.g. functools.lru_cache()
.