---
url: "https://vueda.dev/v3/reference/api/py/vueda.core.serializers/FlexFieldsWriteableNestedSerializerMixin.md"
title: "FlexFieldsWriteableNestedSerializerMixin"
---

# FlexFieldsWriteableNestedSerializerMixin

## Overview

This is a utility mixin making a single class that makes serializers flex &amp; nested writable.

## `apply_flex_fields` {#apply_flex_fields}

Apply sparse-fieldset and expansion options to `fields` in place.

Removes fields that are excluded by ``omit`` or not present in
``fields`` (sparse-fieldset), then replaces fields listed in
``expand`` with their nested serializer instances.
Returns the modified `fields` mapping.

### Signature {#apply_flex_fields-signature}

`apply_flex_fields(self, fields, flex_options)`

#### Parameters {#apply_flex_fields-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| self |  | yes |  |  |
| <span id="apply_flex_fields-param-fields">fields</span> |  | yes |  |  |
| <span id="apply_flex_fields-param-flex_options">flex_options</span> |  | yes |  |  |

### Source {#apply_flex_fields-source}

`server/vueda/core/serializers/__init__.py:221`

## `save` {#save}

Roll back the whole nested write if any related mutation is denied or invalid.

### Signature {#save-signature}

`save(self, kwargs)`

#### Parameters {#save-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| self |  | yes |  |  |
| <span id="save-param-kwargs">kwargs</span> |  | no |  |  |

### Source {#save-source}

`server/vueda/core/serializers/__init__.py:216`

## `to_internal_value` {#to_internal_value}

``?e=`` (expand) names relations whose payload is a nested object rather than a flat
PK, so each expanded relation is swapped for its nested serializer here, before
deserialization, to accept that shape. See the nested-writable-inlines guide for the
query-param contract; this half of flex-field handling is independent of sparse-fieldset
narrowing and stays on the write path.

``?f=``/``?om=`` are not applied here. They narrow the representation only, in
``to_representation`` (via ``ensure_flex_fields_applied``), so a required field they
exclude still fails validation instead of silently losing its validator. Deserialization
must not call ``ensure_flex_fields_applied`` for this reason: that helper runs the full
``apply_flex_fields``, sparse-fieldset removal included, which is exactly what would
drop the validator.

### Signature {#to_internal_value-signature}

`to_internal_value(self, data)`

#### Parameters {#to_internal_value-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| self |  | yes |  |  |
| <span id="to_internal_value-param-data">data</span> |  | yes |  |  |

### Source {#to_internal_value-source}

`server/vueda/core/serializers/__init__.py:266`

## `to_representation` {#to_representation}

``?f=``/``?om=`` (``_flex_options_rep_only``, sourced from query params) narrow the
representation only. Applying them here, rather than in ``to_internal_value``, keeps a
write validating against the serializer's full field set while still narrowing the
response a write returns, since ``to_representation`` runs after ``save()``.

``fields=``/``omit=`` passed as serializer kwargs (``_flex_options_base``) are a
different entry point: ``get_fields()`` applies them before either
``to_internal_value`` or ``to_representation`` runs, so they narrow validation and
representation alike. That is unchanged and deliberate -- a caller constructing a
serializer with explicit kwargs is opting in to restricting both directions, unlike a
client shaping a response with a query parameter.

Delegates the view-bound check and the actual application to
``ensure_flex_fields_applied``, the same helper a caller like
``VuedaViewSet.get_queryset`` uses to resolve ``.fields`` before an instance is ever
serialized (for prefetch planning). Both call sites must agree on when application is
safe and on the ``_flex_fields_rep_applied`` double-application guard, so that logic
lives in one place rather than two copies that could drift.

### Signature {#to_representation-signature}

`to_representation(self, instance)`

#### Parameters {#to_representation-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| self |  | yes |  |  |
| <span id="to_representation-param-instance">instance</span> |  | yes |  |  |

### Source {#to_representation-source}

`server/vueda/core/serializers/__init__.py:241`

## `update` {#update}

### Signature {#update-signature}

`update(self, instance, validated_data)`

#### Parameters {#update-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| self |  | yes |  |  |
| <span id="update-param-instance">instance</span> |  | yes |  |  |
| <span id="update-param-validated_data">validated_data</span> |  | yes |  |  |

### Source {#update-source}

`server/vueda/core/serializers/__init__.py:512`

## `update_or_create_direct_relations` {#update_or_create_direct_relations}

Save each direct relation's row after checking the related viewset's permissions.

An entry that holds only a primary key links the existing row without saving it or
checking permissions, when the field has no save arguments. With save arguments, the
serializer checks and saves the row like any other entry. An unknown primary key raises a validation error
under the field name.

### Signature {#update_or_create_direct_relations-signature}

`update_or_create_direct_relations(self, attrs, relations)`

#### Parameters {#update_or_create_direct_relations-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| self |  | yes |  |  |
| <span id="update_or_create_direct_relations-param-attrs">attrs</span> |  | yes |  |  |
| <span id="update_or_create_direct_relations-param-relations">relations</span> |  | yes |  |  |

### Source {#update_or_create_direct_relations-source}

`server/vueda/core/serializers/__init__.py:414`

## `update_or_create_reverse_relations` {#update_or_create_reverse_relations}

Save each reverse relation's rows, matching submitted pks only against the parent's rows.

drf-writable-nested looks up submitted child pks across the whole child table, then saves
each match with its foreign key set to this parent. A pk that belongs to another parent's
row would move that row here and update it, although the request was authorized only for
this parent. Each relation is saved on its own, so the lookup can be limited to rows that
already belong to this parent. A pk outside that set matches no row, and the library saves
that entry as a new row, as it does for any unknown pk.

Many-to-many entries may link shared rows by pk. Changes to those rows require the
related model's permissions, while parent-owned reverse children keep their matching rules.

### Signature {#update_or_create_reverse_relations-signature}

`update_or_create_reverse_relations(self, instance, reverse_relations)`

#### Parameters {#update_or_create_reverse_relations-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| self |  | yes |  |  |
| <span id="update_or_create_reverse_relations-param-instance">instance</span> |  | yes |  |  |
| <span id="update_or_create_reverse_relations-param-reverse_relations">reverse_relations</span> |  | yes |  |  |

### Source {#update_or_create_reverse_relations-source}

`server/vueda/core/serializers/__init__.py:430`

## Source

`server/vueda/core/serializers/__init__.py:206`
