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:
Args- Must be aTupleorAnyKwargs- Must be aTypedDictorAnyData- Must be aTypedDictorAnySlots- Must be aTypedDictorAny
Here's a full example:
from typing import NotRequired, Tuple, TypedDict, SlotContent, SlotFunc
# Positional inputs
Args = Tuple[int, str]
# Kwargs inputs
class Kwargs(TypedDict):
variable: str
another: int
maybe_var: NotRequired[int] # May be ommited
# Data returned from `get_context_data`
class Data(TypedDict):
variable: str
# The data available to the `my_slot` scoped slot
class MySlotData(TypedDict):
value: int
# Slots
class Slots(TypedDict):
# Use SlotFunc for slot functions.
# The generic specifies the `data` dictionary
my_slot: NotRequired[SlotFunc[MySlotData]]
# SlotContent == Union[str, SafeString]
another_slot: SlotContent
class Button(Component[Args, Kwargs, Slots, Data, JsData, CssData]):
def get_context_data(self, variable, another):
return {
"variable": variable,
}
When you then call Component.render or Component.render_to_response, you will get type hints:
Button.render(
# Error: First arg must be `int`, got `float`
args=(1.25, "abc"),
# Error: Key "another" is missing
kwargs={
"variable": "text",
},
)
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.
Passing additional args or kwargs¤
You may have a function that supports any number of args or kwargs:
This is not supported with the typed components.
As a workaround:
- For
*args, set a positional argument that accepts a list of values:
- For
*kwargs, set a keyword argument that accepts a dictionary of values:
class Kwargs(TypedDict):
variable: str
another: int
# Pass any extra keys under `extra`
extra: Dict[str, any]
Handling no args or no kwargs¤
To declare that a component accepts no Args, Kwargs, etc, you can use EmptyTuple and EmptyDict types:
from django_components import Component, EmptyDict, EmptyTuple
Args = EmptyTuple
Kwargs = Data = Slots = EmptyDict
class Button(Component[Args, Kwargs, Slots, Data, JsData, CssData]):
...
Runtime input validation with types¤
New in version 0.96
NOTE: Kwargs, slots, and data validation is supported only for Python >=3.11
In Python 3.11 and later, when you specify the component types, you will get also runtime validation of the inputs you pass to Component.render or Component.render_to_response.
So, using the example from before, if you ignored the type errors and still ran the following code:
Button.render(
# Error: First arg must be `int`, got `float`
args=(1.25, "abc"),
# Error: Key "another" is missing
kwargs={
"variable": "text",
},
)
This would raise a TypeError:
Component 'Button' expected positional argument at index 0 to be <class 'int'>, got 1.25 of type <class 'float'>
In case you need to skip these errors, you can either set the faulty member to Any, e.g.:
Or you can replace Args with Any altogether, to skip the validation of args:
# Replaced `Args` with `Any`
class Button(Component[Any, Kwargs, Slots, Data, JsData, CssData]):
...
Same applies to kwargs, data, and slots.