
Nested routers in Django Rest Framework (DRF) allow you to define a hierarchical relationship between two or more resources in your API. This can be useful when you have resources that are related to each other, and you want to expose these relationships through your API endpoints.
To implement nested routers in DRF, you can use the DefaultRouter
and NestedDefaultRouter
classes. Here’s an example of how to use these classes to define a nested router:
from rest_framework import routers
router = routers.DefaultRouter()
# Registering the parent resource
router.register(r'parents', ParentViewSet)
# Creating a nested router for child resources
child_router = routers.NestedDefaultRouter(router, r'parents', lookup='parent')
# Registering the child resource
child_router.register(r'children', ChildViewSet, basename='parent-children')
In this example, we first create a DefaultRouter
and register a ParentViewSet
with the r'parents'
URL pattern. Then, we create a NestedDefaultRouter
that takes the parent router and the parent URL pattern as arguments. We also specify a lookup
argument that is used to look up the parent resource when creating child resources. Finally, we register a ChildViewSet
with the r'children'
URL pattern on the child router.
This will create a URL pattern like parents/{parent_id}/children/
, where {parent_id}
is the ID of the parent resource. When a request is made to this URL, DRF will first look up the parent resource using the lookup
argument, and then return the corresponding child resources.
Nested routers can be a powerful tool for organizing your API and making it more intuitive for your users to interact with. However, they can also add complexity to your code, so it’s important to carefully consider your API design and use nested routers only when they make sense.
A Simple Project on Nested Routers in Django
For this example, let’s assume that we have two resources: Book
and Chapter
. A Book
can have many Chapter
s, and we want to define a nested relationship between these resources in our API.
Here are the steps to implement nested routers in Django:
1. Install Django and Django Rest Framework using pip:
pip install django djangorestframework
2. Create a new Django project:
django-admin startproject nested_routers_example
3. Create a new Django app called books
:
cd nested_routers_example
python manage.py startapp books
4. Define the models for Book
and Chapter
in books/models.py
:
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
class Chapter(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE, related_name='chapters')
title = models.CharField(max_length=100)
5. Create a serializers for Book
and Chapter
in books/serializers.py
:
from rest_framework import serializers
from .models import Book, Chapter
class ChapterSerializer(serializers.ModelSerializer):
class Meta:
model = Chapter
fields = ('id', 'title')
class BookSerializer(serializers.ModelSerializer):
chapters = ChapterSerializer(many=True, read_only=True)
class Meta:
model = Book
fields = ('id', 'title', 'chapters')
6. Define the viewsets for Book
and Chapter
in books/views.py
:
from rest_framework import viewsets
from .models import Book, Chapter
from .serializers import BookSerializer, ChapterSerializer
class ChapterViewSet(viewsets.ModelViewSet):
queryset = Chapter.objects.all()
serializer_class = ChapterSerializer
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
7. Create a new urls.py
file in the books
app:
from rest_framework import routers
from django.urls import path, include
from .views import BookViewSet, ChapterViewSet
router = routers.DefaultRouter()
router.register(r'books', BookViewSet)
# Nested router for chapters
book_router = routers.NestedDefaultRouter(router, r'books', lookup='book')
book_router.register(r'chapters', ChapterViewSet)
urlpatterns = [
path('', include(router.urls)),
path('', include(book_router.urls)),
]
In this code, we first define a DefaultRouter
and register the BookViewSet
with the URL pattern r'books'
. Then, we create a NestedDefaultRouter
for the ChapterViewSet
that takes the book_router
and the book
lookup argument. Finally, we register the ChapterViewSet
with the URL pattern r'chapters'
.
8. Add the books
app to the INSTALLED_APPS
list in nested_routers_example/settings.py
.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'books', # add the books app here
]
9. Create the database tables:
python manage.py migrate
10 .Start the development server:
python manage.py runserver
Now you can test the API by sending HTTP requests to `http://localhost: