This version is in beta. Some features may change before release.

Nested writes

Create a parent and its children in one POST with writable nested serializers.

Writable nested objects

Create a parent row and its children in a single request. Declare the nested relationship on the resource:

Code
rust
RestPlugin::default()
.resource(ResourceConfig::for_::<Order>().nested("items", "order_item"))

Now a POST whose body carries the nested array creates everything:

Code
http
POST /api/order/
Content-Type: application/json
 
{
"customer": "Ada",
"items": [
{ "product": "Widget", "qty": 2 },
{ "product": "Gadget", "qty": 1 }
]
}

The order is inserted first; then each item is inserted with its foreign key to the order set automatically, so you don't repeat the parent id in each child. The response echoes the created children back:

Code
json
{
"id": 7,
"customer": "Ada",
"items": [
{ "id": 1, "order": 7, "product": "Widget", "qty": 2 },
{ "id": 2, "order": 7, "product": "Gadget", "qty": 1 }
]
}

How the FK is found

.nested("items", "order_item") says "the items array holds order_item rows." The framework discovers which column on order_item points back at order (the column whose foreign key targets the parent's table) and fills it. If the child has no FK to the parent, or more than one (ambiguous), the request fails with a clear 400.

All-or-nothing on failure

If any child fails validation (a missing required field, a bad FK, a constraint clash), the whole write is rolled back in a single database transaction - the parent and all children either commit together or not at all, so you never get a half-created parent:

Code
http
POST /api/order/ { "customer": "Grace", "items": [ {"product":"ok","qty":1}, {"qty":5} ] }
400 (the second item has no product)no order is created
Info

This is a real database transaction: create_nested opens one umbral::db::Transaction, inserts the parent + every child on it (DynQuerySet::insert_json_in_tx), and commit()s only after they all succeed. Any failure - a bad child, a constraint clash, or even a process crash between inserts - leaves zero rows, because the transaction is never committed and the database rolls it back. (This replaced an earlier compensating delete-on-failure handler; see planning/orm_fixes.md #2.)

Scope

One level of nesting (a parent and its direct children). Declare multiple nested arrays by calling .nested(...) more than once. The flat create path is unchanged and carries zero overhead when no nested resources are declared.

See also

restnestedserializersrelations