DRF Nested Routers

0.95.0 · active · verified Sat Apr 11

DRF Nested Routers is a Python library that extends Django REST Framework (DRF) to facilitate the creation of nested resources. It provides specialized routers and relation fields necessary for building a full REST URL structure where one resource hierarchically depends on another (e.g., `/authors/{author_pk}/books/`). This is crucial when child resources logically exist only within the context of their parent. The library is actively maintained, with the current version being 0.95.0, and typically releases updates to maintain compatibility with new Django and DRF versions.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to set up nested routes for `Domains` and their `Nameservers`. It uses `DefaultRouter` for the base resource and `NestedDefaultRouter` for the nested resource. The `lookup` argument in `NestedDefaultRouter` specifies the URL keyword argument that will be used to filter child resources (e.g., `domain_pk`). The `basename` argument is crucial for correctly generating URL patterns and reverse lookups, especially for the nested router.

from django.db import models
from rest_framework import viewsets, serializers
from rest_framework_nested import routers
from django.urls import path, include

# models.py
class Domain(models.Model):
    name = models.CharField(max_length=255)

    def __str__(self):
        return self.name

class Nameserver(models.Model):
    domain = models.ForeignKey(Domain, related_name='nameservers', on_delete=models.CASCADE)
    hostname = models.CharField(max_length=255)

    def __str__(self):
        return f'{self.hostname} ({self.domain.name})'

# serializers.py (Optional, for hyperlinked relations)
class NameserverSerializer(serializers.ModelSerializer):
    class Meta:
        model = Nameserver
        fields = ['id', 'hostname']

class DomainSerializer(serializers.ModelSerializer):
    nameservers = NameserverSerializer(many=True, read_only=True)
    class Meta:
        model = Domain
        fields = ['id', 'name', 'nameservers']

# views.py
class DomainViewSet(viewsets.ModelViewSet):
    queryset = Domain.objects.all()
    serializer_class = DomainSerializer

class NameserverViewSet(viewsets.ModelViewSet):
    serializer_class = NameserverSerializer

    def get_queryset(self):
        return self.queryset.filter(domain=self.kwargs['domain_pk'])

    def perform_create(self, serializer):
        domain = Domain.objects.get(pk=self.kwargs['domain_pk'])
        serializer.save(domain=domain)

# urls.py
router = routers.DefaultRouter()
router.register(r'domains', DomainViewSet, basename='domain')

domains_router = routers.NestedDefaultRouter(router, r'domains', lookup='domain')
domains_router.register(r'nameservers', NameserverViewSet, basename='domain-nameserver')

urlpatterns = [
    path('', include(router.urls)),
    path('', include(domains_router.urls)),
]

# Example usage in a Django project's main urls.py:
# from django.urls import path, include
# from myapp import urls as myapp_urls
# urlpatterns = [
#     path('api/', include(myapp_urls)),
# ]

view raw JSON →