-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Problem
There's an error where Pydantic incorrectly coerces SafeString
to str
.
The end result is that Django template receives a plain string instead of SafeString
, thus incorrectly escaping the HTML content:

This happens only when I:
- Declare slots with
Component.Slots
- Use Pydantic's
BaseModel
to define theSlots
class - Pass in the slots as
SafeString
E.g.
from pydantic import BaseModel
from django_components import Component, SlotInput
class Table(Component):
class Slots(BaseModel):
project_nav: SlotInput
Table.render(
slots={
"project_nav": ProjectNav.render(...),
}
)
I know that this is an issue with how Pydantic handles the SlotInput
type, because the values are coerced to str
only once Slots
class is instantiated:

Solution
I have recently read through Pydantic docs page on union types and they have an unusual way of handling unions, so I believe this might the case.
Don't know the internals of Pydantic, so I think we should raise this with Pydantic project to ask for help.
For context, the definition of SlotInput
is:
TSlotData = TypeVar("TSlotData", bound=Mapping)
SlotResult = Union[str, SafeString]
class SlotFunc(Protocol, Generic[TSlotData]):
def __call__(self, ctx: SlotContext[TSlotData]) -> SlotResult:
...
@dataclass
class Slot(Generic[TSlotData]):
...
SlotInput = Union[SlotResult, SlotFunc[TSlotData], Slot[TSlotData]]
Moreover, definition of SafeString
is
class SafeString(str, SafeData):
...
And our Component.render()
returns SafeString
instances. So I don't understand why Pydantic is coercing that to str
instead of SafeString
.
Based on their "exactness" logic in their docs, I would have expected that SafeString
instance would match SafeString
class over str