Skip to content

Model Serializers

Our views work with model instances, but a JSON response can only hold plain values like strings, numbers, and lists. To return an animal as JSON, we need to convert it first.

Install DRF

shell
uv add "djangorestframework~=3.18.3"

DRF is a Django app, with its own templates and static files for the browsable API, so it goes in INSTALLED_APPS. Add it below our own apps in config/settings.py:

config/settings.py
INSTALLED_APPS = [
    "animals",
    "accounts",
    "rest_framework",

Serializers

A serializer converts model instances into plain Python values that DRF can render as JSON. It also works in the other direction: it validates the data a client sends, and its save() turns it into a model instance.

The Animal Serializer

Our serializer needs the fields the model already has, so we'll use a ModelSerializer, which builds its fields from a model the way a ModelForm does. Create animals/serializers.py:

animals/serializers.py
from rest_framework import serializers

from .models import Animal


class AnimalSerializer(serializers.ModelSerializer):
    class Meta:
        model = Animal
        fields = [
            "id",
            "name",
            "species",
            "breed",
            "birth_date",
            "age_label",
            "description",
            "photo",
            "status",
            "intake_date",
        ]

Meta.model names the model, and fields lists the fields the JSON will include. For each one, ModelSerializer creates a matching serializer field: a date field for birth_date, and a choice field for species. It also copies each model field's rules, such as max_length and the choices, for validating data that comes in.

age_label isn't a field: it's our model's method. A method's name in fields becomes a read-only field, with the method's return value.

Listing every field with __all__

ModelSerializer also accepts fields = "__all__", which includes every field on the model. A field added to the model later then appears in the API as soon as it's migrated, so we list ours one by one.