.. _read-only-fields:

Read only fields
----------------

Sometimes, fields should never be able to be specified by the client. For example, upon creation of a new resource
instance, the ``id`` field of a model should be generated by the server and not specified by the client.

.. literalinclude:: /examples/data_transfer_objects/factory/tutorial/read_only_fields_error.py
   :language: python
   :linenos:
   :emphasize-lines: 14

In this adjustment, we add an ``id`` field to the ``Person`` model. We also create a new class, ``WriteDTO`` that is
instructed to ignore the ``id`` attribute.

The ``WriteDTO`` class is assigned to the handler via the ``dto`` kwarg (``dto=WriteDTO``) meaning that the ``id`` field
will be ignored from any data received from the client when creating a new ``Person`` instance.

When we try to create a new ``Person`` instance with an ``id`` field specified, we get an error:

.. image:: images/read_only_fields_error.png
   :align: center

What's happening? The DTO is trying to construct an instance of the ``Person`` model but we have excluded the ``id``
field from the accepted client data. The ``id`` field is required by the ``Person`` model, so the model constructor
raises an error.

There is more than one way to address this issue, for example we could assign a default value to the ``id`` field and
overwrite the default in the handler, or we could create an entirely separate model that has no ``id`` field, and
transfer the data from that to the ``Person`` model in the handler. However, Litestar has a built-in solution for this:
:class:`DTOData <litestar.dto.data_structures.DTOData>`.
