Typing and validation
Adding type hints with Generics¤
New in version 0.92
The Component
class optionally accepts type parameters that allow you to specify the types of args, kwargs, slots, and data.
Use this to add type hints to your components, or to validate component inputs.
from django_components import Component
ButtonType = Component[Args, Kwargs, Slots, Data, JsData, CssData]
class Button(ButtonType):
template_file = "button.html"
def get_context_data(self, *args, **kwargs):
...
The generic parameters are:
Args
- Positional arguments, must be aTuple
orAny
Kwargs
- Keyword arguments, must be aTypedDict
orAny
Slots
- Slots, must be aTypedDict
orAny
Data
- Data returned fromget_context_data()
, must be aTypedDict
orAny
JsData
- Data returned fromget_js_data()
, must be aTypedDict
orAny
CssData
- Data returned fromget_css_data()
, must be aTypedDict
orAny
Example¤
from typing import NotRequired, Tuple, TypedDict
from pydantic import BaseModel
from django_components import Component, SlotContent, SlotFunc
###########################################
# 1. Define the types
###########################################
# Positional inputs
ButtonArgs = Tuple[str, ...]
# Keyword inputs
class ButtonKwargs(TypedDict):
name: str
age: int
maybe_var: NotRequired[int] # May be ommited
# The data available to the `footer` scoped slot
class ButtonFooterSlotData(TypedDict):
value: int
# Slots
class ButtonSlots(TypedDict):
# SlotContent == str or slot func
header: SlotContent
# Use SlotFunc for slot functions.
# The generic specifies the data available to the slot function
footer: NotRequired[SlotFunc[ButtonFooterSlotData]]
# Data returned from `get_context_data`
class ButtonData(BaseModel):
data1: str
data2: int
# Data returned from `get_js_data`
class ButtonJsData(BaseModel):
js_data1: str
js_data2: int
# Data returned from `get_css_data`
class ButtonCssData(BaseModel):
css_data1: str
css_data2: int
###########################################
# 2. Define the component with those types
###########################################
ButtonType = Component[
ButtonArgs,
ButtonKwargs,
ButtonSlots,
ButtonData,
ButtonJsData,
ButtonCssData,
]
class Button(ButtonType):
def get_context_data(self, *args, **kwargs):
...
When you then call Component.render
or Component.render_to_response
, you will get type hints:
Button.render(
# ERROR: Expects a string
args=(123,),
kwargs={
"name": "John",
# ERROR: Expects an integer
"age": "invalid",
},
slots={
"header": "...",
# ERROR: Expects key "footer"
"foo": "invalid",
},
)
If you don't want to validate some parts, set them to Any
.
ButtonType = Component[
ButtonArgs,
ButtonKwargs,
ButtonSlots,
Any,
Any,
Any,
]
class Button(ButtonType):
...
Passing variadic args and kwargs¤
You may have a function that accepts a variable number of args or kwargs:
This is not supported with the typed components.
As a workaround:
-
For a variable number of positional arguments (
*args
), set a positional argument that accepts a list of values: -
For a variable number of keyword arguments (
**kwargs
), set a keyword argument that accepts a dictionary of values:
Handling no args or no kwargs¤
To declare that a component accepts no args, kwargs, etc, you can use the EmptyTuple
and EmptyDict
types:
from django_components import Component, EmptyDict, EmptyTuple
class Button(Component[EmptyTuple, EmptyDict, EmptyDict, EmptyDict, EmptyDict, EmptyDict]):
...
Runtime input validation with types¤
Warning
Input validation was part of Django Components from version 0.96 to 0.135.
Since v0.136, input validation is available as a separate extension.
To enable input validation, you need to install the djc-ext-pydantic
extension:
And add the extension to your project:
djc-ext-pydantic
integrates Pydantic for input and data validation. It uses the types defined on the component's class to validate inputs of Django components.
Usage for Python <3.11¤
On Python 3.8-3.10, use typing_extensions
Additionally on Python 3.8-3.9, also import annotations
:
Moreover, on 3.10 and less, you may not be able to use NotRequired
, and instead you will need to mark either all keys are required, or all keys as optional, using TypeDict's total
kwarg.
See PEP-655 for more info.