Challenge 2: Build a Full CRUD API — Possible Solution ==================================================================== # catalog/serializers.py from rest_framework import serializers from .models import Author class AuthorSerializer(serializers.ModelSerializer): class Meta: model = Author fields = ["id", "name", "bio"] # catalog/views.py from rest_framework import viewsets from .models import Author from .serializers import AuthorSerializer class AuthorViewSet(viewsets.ModelViewSet): queryset = Author.objects.all() serializer_class = AuthorSerializer # catalog/urls.py from rest_framework.routers import DefaultRouter from .views import AuthorViewSet router = DefaultRouter() router.register("authors", AuthorViewSet) urlpatterns = router.urls # mysite/urls.py (the project's root, per Course 1 Chapter 2's include() pattern) from django.urls import path, include urlpatterns = [ path("api/", include("catalog.urls")), ] RESULTING ROUTES (mounted under /api/ from the project root) ------------------------------------------------------------------ GET /api/authors/ -> list all authors POST /api/authors/ -> create a new author GET /api/authors/{id}/ -> retrieve one author PUT /api/authors/{id}/ -> update one author (full replace) PATCH /api/authors/{id}/ -> partially update one author DELETE /api/authors/{id}/ -> delete one author WHY THIS WORKS -------------- - AuthorViewSet only needs two class attributes — queryset (which rows) and serializer_class (how to shape them) — and ModelViewSet's parent class implements every one of the six actions above using those two pieces of information; nothing else needed to be written by hand. - router.register("authors", AuthorViewSet) is the single line that replaces what would otherwise be five or six separate path() entries in urlpatterns, one per action — directly mirroring the chapter's comparison to Rails' resources :books generating multiple routes from one declaration. - Mounting catalog.urls under "api/" in the project's root urls.py reuses the exact include() pattern from Course 1, Chapter 2 — the app's own urls.py (in this case, router.urls) never needs to know or care what prefix it ends up served under.