What's Changed
Added support for Python 3.14!
Feat
-
You can now define component input defaults directly on
Component.Kwargs
.Before, the defaults had to be defined on a separate
Component.Defaults
class:class ProfileCard(Component): class Kwargs: user_id: int show_details: bool class Defaults: show_details = True
Now, django-components can detect the defaults from
Component.Kwargs
and apply
them. So you can mergeComponent.Kwargs
withComponent.Defaults
:class ProfileCard(Component): class Kwargs: user_id: int show_details: bool = True
NOTE: This applies only when
Component.Kwargs
is a NamedTuple or dataclass. -
New helper
get_component_defaults()
:Now, the defaults may be defined on either
Component.Defaults
andComponent.Kwargs
classes.To get a final, merged dictionary of all the component's defaults, use
get_component_defaults()
:from django_components import Component, Default, get_component_defaults class MyTable(Component): class Kwargs: position: str order: int items: list[int] variable: str = "from_kwargs" class Defaults: position: str = "left" items = Default(lambda: [1, 2, 3]) defaults = get_component_defaults(MyTable) # { # "position": "left", # "items": [1, 2, 3], # "variable": "from_kwargs", # }
-
Simpler syntax for defining component inputs:
When defining
Args
,Kwargs
,Slots
,JsData
,CssData
,TemplateData
, these data classes now don't have to subclass any other class.If they are not subclassing (nor
@dataclass
), these data classes will be automatically converted toNamedTuples
:Before - the
Args
,Kwargs
, andSlots
(etc..) had to be NamedTuples, dataclasses, or Pydantic models:from typing import NamedTuple from django_components import Component class Button(Component): class Args(NamedTuple): size: int text: str class Kwargs(NamedTuple): variable: str maybe_var: Optional[int] = None class Slots(NamedTuple): my_slot: Optional[SlotInput] = None def get_template_data(self, args: Args, kwargs: Kwargs, slots: Slots, context: Context): ...
Now these classes are automatically converted to
NamedTuples
if they don't subclass anything else:class Button(Component): class Args: # Same as `Args(NamedTuple)` size: int text: str class Kwargs: # Same as `Kwargs(NamedTuple)` variable: str maybe_var: Optional[int] = None class Slots: # Same as `Slots(NamedTuple)` my_slot: Optional[SlotInput] = None def get_template_data(self, args: Args, kwargs: Kwargs, slots: Slots, context: Context): ...
Refactor
-
Extension authors: The
ExtensionComponentConfig
can be instantiated withNone
instead of a component instance.This allows to call component-level extension methods outside of the normal rendering lifecycle.
Full Changelog: 0.142.3...0.143.0