Mutations¶
Sync helpers¶
apply_input ¶
apply_input(
instance: Model,
data: Any,
*,
field_map: dict[str, str] | None = None,
exclude_fields: list[str] | None = None,
) -> ChangeResult
Set attributes from data onto instance without saving.
Returns a ChangeResult
describing fields whose value actually changed. Useful when a service wants to
inspect what the input would change before deciding whether to persist.
create_from_input ¶
create_from_input(
model: type[ModelT],
data: Any,
*,
field_map: dict[str, str] | None = None,
exclude_fields: list[str] | None = None,
m2m: dict[str, Any] | None = None,
children: Mapping[str, ChildSpec] | None = None,
relations: Mapping[str, RelationSpec] | None = None,
context: Mapping[str, Any] | None = None,
) -> ChangeResult[ModelT]
Build, save(), and return a fresh instance of model.
Regular fields come from data (a dataclass, dict, or object with __dict__);
M2M assignments are applied post-save via the m2m kwarg, mapping attribute name
to the value to set(). That argument assigns rows which already exist; writing
the target rows from the payload is a
ManyToManySpec
in relations. Both still ship — they are different jobs — but a relation named
by both is refused, since it would be written twice and keep whichever ran last.
relations maps a relation name to the spec for its kind; the nested payload is
read from data[relation] and written in the order the kind dictates, not the
order the map is spelled in (see
RelationPhase).
children is the reverse-FK alias — the same map under the name it shipped as —
and a name declared in both raises. Keep the whole call inside the service's atomic
block.
context is an opaque mapping forwarded verbatim into the pool of any
per-child service a
ChildSpec declares. This
helper never reads it — it exists so per-row work downstream can see the acting
caller. The default model-service factories populate it from the framework's kwargs
pool automatically; a hand-written service opts in with context=kwargs.
update_from_input ¶
update_from_input(
instance: ModelT,
data: Any,
*,
field_map: dict[str, str] | None = None,
exclude_fields: list[str] | None = None,
m2m: dict[str, Any] | None = None,
update_fields: bool | list[str] = True,
children: Mapping[str, ChildSpec] | None = None,
relations: Mapping[str, RelationSpec] | None = None,
context: Mapping[str, Any] | None = None,
) -> ChangeResult[ModelT]
Update instance with values from data, persisting only deltas.
By default (update_fields=True), the save call uses
update_fields=<changed> to write the minimal set of columns.
auto_now=True fields (e.g. updated_at) are automatically added to
that list so they are refreshed alongside the mutation. Pass False to
perform a full save, or an explicit list to control exactly which columns
are written (no auto-injection in that case).
m2m assigns many-to-many rows that already exist;
ManyToManySpec
in relations writes the target rows from the payload instead. A relation named
by both is refused rather than written twice.
relations maps a relation name to the spec for its kind (children
is the reverse-FK alias). The nested payload from data[relation] is
reconciled with what is already there — create / update / orphan-remove per
the spec — and a relation the input omits is left untouched. Kinds are
written in the order their class dictates, so a forward foreign key is
resolved before this instance is saved and the assignment rides the same
diff and update_fields path as any other column. Keep the call inside
the service's atomic block.
A relation that was written stays readable off the returned instance. The one-row kinds resolve their row by re-querying, so the parent's cached related object is replaced with the row that was written — and dropped where the write removed it — rather than left holding pre-write values.
context is an opaque mapping forwarded verbatim into the pool of any
per-child service a
ChildSpec declares; this
helper never reads it. See
create_from_input.
Async helpers¶
acreate_from_input
async
¶
acreate_from_input(
model: type[ModelT],
data: Any,
*,
field_map: dict[str, str] | None = None,
exclude_fields: list[str] | None = None,
m2m: dict[str, Any] | None = None,
children: Mapping[str, ChildSpec] | None = None,
relations: Mapping[str, RelationSpec] | None = None,
context: Mapping[str, Any] | None = None,
) -> ChangeResult[ModelT]
Async sibling of
create_from_input
using asave()/aset().
aupdate_from_input
async
¶
aupdate_from_input(
instance: ModelT,
data: Any,
*,
field_map: dict[str, str] | None = None,
exclude_fields: list[str] | None = None,
m2m: dict[str, Any] | None = None,
update_fields: bool | list[str] = True,
children: Mapping[str, ChildSpec] | None = None,
relations: Mapping[str, RelationSpec] | None = None,
context: Mapping[str, Any] | None = None,
) -> ChangeResult[ModelT]
Async sibling of
update_from_input
using asave()/aset().