mirror of
https://github.com/django-components/django-components.git
synced 2025-08-04 14:28:18 +00:00
feat: component caching (#1097)
* feat: allow to set defaults * refactor: remove input validation and link to it * feat: component URL * feat: component caching * refactor: Mark `OnComponentRenderedContext` as extension hook for docs * docs: update changelog * refactor: simplify hash methods
This commit is contained in:
parent
ef15117459
commit
b6994e9ad3
17 changed files with 655 additions and 45 deletions
|
@ -5,6 +5,7 @@ nav:
|
|||
- Prop drilling and provide / inject: provide_inject.md
|
||||
- Lifecycle hooks: hooks.md
|
||||
- Registering components: component_registry.md
|
||||
- Component caching: component_caching.md
|
||||
- Typing and validation: typing_and_validation.md
|
||||
- Custom template tags: template_tags.md
|
||||
- Tag formatters: tag_formatter.md
|
||||
|
|
105
docs/concepts/advanced/component_caching.md
Normal file
105
docs/concepts/advanced/component_caching.md
Normal file
|
@ -0,0 +1,105 @@
|
|||
Component caching allows you to store the rendered output of a component. Next time the component is rendered
|
||||
with the same input, the cached output is returned instead of re-rendering the component.
|
||||
|
||||
This is particularly useful for components that are expensive to render or do not change frequently.
|
||||
|
||||
!!! info
|
||||
|
||||
Component caching uses Django's cache framework, so you can use any cache backend that is supported by Django.
|
||||
|
||||
### Enabling caching
|
||||
|
||||
Caching is disabled by default.
|
||||
|
||||
To enable caching for a component, set [`Component.Cache.enabled`](../../reference/api.md#django_components.ComponentCache.enabled) to `True`:
|
||||
|
||||
```python
|
||||
from django_components import Component
|
||||
|
||||
class MyComponent(Component):
|
||||
class Cache:
|
||||
enabled = True
|
||||
```
|
||||
|
||||
### Time-to-live (TTL)
|
||||
|
||||
You can specify a time-to-live (TTL) for the cache entry with [`Component.Cache.ttl`](../../reference/api.md#django_components.ComponentCache.ttl), which determines how long the entry remains valid. The TTL is specified in seconds.
|
||||
|
||||
```python
|
||||
class MyComponent(Component):
|
||||
class Cache:
|
||||
enabled = True
|
||||
ttl = 60 * 60 * 24 # 1 day
|
||||
```
|
||||
|
||||
- If `ttl > 0`, entries are cached for the specified number of seconds.
|
||||
- If `ttl = -1`, entries are cached indefinitely.
|
||||
- If `ttl = 0`, entries are not cached.
|
||||
- If `ttl = None`, the default TTL is used.
|
||||
|
||||
### Custom cache name
|
||||
|
||||
Since component caching uses Django's cache framework, you can specify a custom cache name with [`Component.Cache.cache_name`](../../reference/api.md#django_components.ComponentCache.cache_name) to use a different cache backend:
|
||||
|
||||
```python
|
||||
class MyComponent(Component):
|
||||
class Cache:
|
||||
enabled = True
|
||||
cache_name = "my_cache"
|
||||
```
|
||||
|
||||
### Cache key generation
|
||||
|
||||
By default, the cache key is generated based on the component's input (args and kwargs). So the following two calls would generate separate entries in the cache:
|
||||
|
||||
```py
|
||||
MyComponent.render(name="Alice")
|
||||
MyComponent.render(name="Bob")
|
||||
```
|
||||
|
||||
However, you have full control over the cache key generation. As such, you can:
|
||||
|
||||
- Cache the component on all inputs (default)
|
||||
- Cache the component on particular inputs
|
||||
- Cache the component irrespective of the inputs
|
||||
|
||||
To achieve that, you can override
|
||||
the [`Component.Cache.hash()`](../../reference/api.md#django_components.ComponentCache.hash)
|
||||
method to customize how arguments are hashed into the cache key.
|
||||
|
||||
```python
|
||||
class MyComponent(Component):
|
||||
class Cache:
|
||||
enabled = True
|
||||
|
||||
def hash(self, *args, **kwargs):
|
||||
return f"{json.dumps(args)}:{json.dumps(kwargs)}"
|
||||
```
|
||||
|
||||
For even more control, you can override other methods available on the [`ComponentCache`](../../reference/api.md#django_components.ComponentCache) class.
|
||||
|
||||
!!! warning
|
||||
|
||||
The default implementation of `Cache.hash()` simply serializes the input into a string.
|
||||
As such, it might not be suitable if you need to hash complex objects like Models.
|
||||
|
||||
### Example
|
||||
|
||||
Here's a complete example of a component with caching enabled:
|
||||
|
||||
```python
|
||||
from django_components import Component
|
||||
|
||||
class MyComponent(Component):
|
||||
template = "Hello, {{ name }}"
|
||||
|
||||
class Cache:
|
||||
enabled = True
|
||||
ttl = 300 # Cache for 5 minutes
|
||||
cache_name = "my_cache"
|
||||
|
||||
def get_context_data(self, name, **kwargs):
|
||||
return {"name": name}
|
||||
```
|
||||
|
||||
In this example, the component's rendered output is cached for 5 minutes using the `my_cache` backend.
|
|
@ -1,8 +1,20 @@
|
|||
This page describes the kinds of assets that django-components caches and how to configure the cache backends.
|
||||
|
||||
## Component caching
|
||||
|
||||
You can cache the output of your components by setting the [`Component.Cache`](../../reference/api.md#django_components.Component.Cache) options.
|
||||
|
||||
Read more about [Component caching](../../concepts/advanced/component_caching.md).
|
||||
|
||||
## Component's JS and CSS files
|
||||
|
||||
django-components caches the JS and CSS files associated with your components. This enables components to be rendered as HTML fragments and still having the associated JS and CSS files loaded with them.
|
||||
django-components simultaneously supports:
|
||||
|
||||
- Rendering and fetching components as HTML fragments
|
||||
- Allowing components (even fragments) to have JS and CSS files associated with them
|
||||
- Features like JS/CSS variables or CSS scoping
|
||||
|
||||
To achieve all this, django-components defines additional temporary JS and CSS files. These temporary files need to be stored somewhere, so that they can be fetched by the browser when the component is rendered as a fragment. And for that, django-components uses Django's cache framework.
|
||||
|
||||
This includes:
|
||||
|
||||
|
|
|
@ -332,13 +332,13 @@ Django-components functionality can be extended with "extensions". Extensions al
|
|||
|
||||
Some of the extensions include:
|
||||
|
||||
- [Component caching](https://github.com/django-components/django-components/blob/master/src/django_components/extensions/cache.py)
|
||||
- [Django View integration](https://github.com/django-components/django-components/blob/master/src/django_components/extensions/view.py)
|
||||
- [Component defaults](https://github.com/django-components/django-components/blob/master/src/django_components/extensions/defaults.py)
|
||||
- [Pydantic integration (input validation)](https://github.com/django-components/djc-ext-pydantic)
|
||||
|
||||
Some of the planned extensions include:
|
||||
|
||||
- Caching
|
||||
- AlpineJS integration
|
||||
- Storybook integration
|
||||
- Component-level benchmarking with asv
|
||||
|
@ -365,10 +365,20 @@ def test_my_table():
|
|||
assert rendered == "<table>My table</table>"
|
||||
```
|
||||
|
||||
### Handle large projects with ease
|
||||
### Caching
|
||||
|
||||
- Components can be infinitely nested.
|
||||
- (Soon) Optimize performance with component-level caching
|
||||
- Components can be cached using Django's cache framework.
|
||||
- Components are cached based on their input. Or you can write custom caching logic.
|
||||
- Caching rules can be configured on a per-component basis.
|
||||
|
||||
```py
|
||||
from django_components import Component
|
||||
|
||||
class MyComponent(Component):
|
||||
class Cache:
|
||||
enabled = True
|
||||
ttl = 60 * 60 * 24 # 1 day
|
||||
```
|
||||
|
||||
### Debugging features
|
||||
|
||||
|
|
|
@ -15,6 +15,18 @@
|
|||
options:
|
||||
show_if_no_docstring: true
|
||||
|
||||
::: django_components.ComponentCache
|
||||
options:
|
||||
show_if_no_docstring: true
|
||||
|
||||
::: django_components.ComponentCommand
|
||||
options:
|
||||
show_if_no_docstring: true
|
||||
|
||||
::: django_components.ComponentDefaults
|
||||
options:
|
||||
show_if_no_docstring: true
|
||||
|
||||
::: django_components.ComponentExtension
|
||||
options:
|
||||
show_if_no_docstring: true
|
||||
|
|
|
@ -124,7 +124,7 @@ name | type | description
|
|||
`component` | [`Component`](../api#django_components.Component) | The Component instance that is being rendered
|
||||
`component_cls` | [`Type[Component]`](../api#django_components.Component) | The Component class
|
||||
`component_id` | `str` | The unique identifier for this component instance
|
||||
`template` | `str` | The rendered template
|
||||
`result` | `str` | The rendered component
|
||||
|
||||
::: django_components.extension.ComponentExtension.on_component_unregistered
|
||||
options:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue