General and Nested Routers

Learn via video courses
Topics Covered

Overview

Routes in Django are defined as a path that map a URL with a View function to handle the incoming request. In nested routers, a resourceful route declares your index's routes in a single line of code rather than separately.

Introduction

While working on a project, we map different URLs for different view functions.

For example, if we are building an API for a school management system, then we will have different routes.

  • /api/students/ - get the list of all the students
  • /api/students/{class}/ - get the details of all the students from a particular class
  • /api/students/{class}/sections - get the list of all the sections in a particular class
  • /api/students/{class}/sections/{section_id} - get the details of all the students from a particular section of the class.

Till this part and even further, mapping the URL is possible. But if this gets scaled up and we need to create many nested routers then we may face problems and also the code readability will get reduced. In this case, we use a Nested router, which we will look into further in the article.

Usage

There are several methods by which you can map or include the URLs. At first, then we can use SimpleRouter() and append the URLs to an existing list. For example, for our school management system, we want to add URLs for students and classes, we can implement this as shown below

The other method is by including the URLs, which we will see in the next section.

Using Include with Routers

We can simply include the routers.urls in the existing list of urlpatterns. For that, we first need to import the included method by writing the following script.

Now, we can simply use this method to include the URLs as shown in the code below

We can also add the application and instance namespace while including the routers.

Routing for Extra Actions

By using the @action decorator to indicate a method, a viewset can mark additional actions for routing. The produced routes will incorporate these additional steps.

To implement it, at first we need to import the action decorator.

We can now use this decorator to use a function within a class in the views.py file. For example,

API Guide

SimpleRouter

The typical set of list, create, retrieve, update, partial update, and delete actions are all routed through this Simple Router.

By default, the Simple router looks like this,

A trailing slash is added after each SimpleRouter which can be modified by changing it to false.

DefaultRouter

In addition to having a default API root view that produces a response with links to all the list views, the Default Router router is identical to SimpleRouter as stated above.

In general, a DefaultRouter can be used as

Unlike SimpleRouter, while instantiating the router, the trailing slash option can be set to False to eliminate the trailing slashes from URL routes.

Custom Routers

In case we need to achieve specific requirements about how the URLs for the API are structured, Custom Routers can be very useful in this scenario.

The .routes attribute is used to template the URL patterns and its attribute is a list of Route named tuples whose arguments are

  • url - a string containing the following format strings that represent the URL to be forwarded.
    • prefix - the prefix for the URLs for these routes
    • lookup - the lookup field that was utilized to compare against one specific instance.
    • trailing_slash - depending on the trailing_slash option, either a '/' or an empty string will be returned.
  • mapping - a dictionary of HTTP method names that correspond to view methods.
  • name - the name defined is used in the reverse call, it generally includes basename as the name.
  • initkwargs - a dictionary containing any extra arguments that need to be given when instantiating the view.

Customizing Dynamic Routes

When it comes to customizing dynamic routes, even the routing of the @action decorator can be modified. The DynamicRoute named tuple can be added to the.routes list, with the detailed argument set to the proper value for both list-based and detail-based routes, to implement this.

DynamicRoute accepts the following arguments

  • url - works the same as it works in Route as shown above, additionally it can include url_path.
  • name - used in reverse calls and include basename and url_name.
  • initkwargs - a dictionary of any extra arguments that should be given when creating the view.

Example Here is some following example to implement custom and dynamic routes.

For custom routes, we have seen that we have arguments like url, mapping, name, and details as shown in to code below

And for Dynamic routes, we can do the same as shown in the code below

Advanced Custom Routers

Advanced custom routers enable us to override the methods we defined in the earlier section.

Third-Party Packages

Some third-party packages can be used to achieve the goal of the DRF-nested routers.

DRF Nested Routers

A third-party package that aims to provide routers and fields to create nested resources in the Django Rest Framework.

We first need to install from the pip package

To use and implement this in our code, we need to import routers from rest_framework_nested which is a module of drf-nested-routers.

Now, this router can be used to instantiate a SimpleRouter and register.

ModelRouter (wq.db.rest)

Introducing wq. db, it is a set of Python modules for generating reliable, adaptable schemas and REST APIs that may be used to build field data-gathering apps with incremental improvements.

To implement this, we first need to install it from the pip package as

Then we can use it as shown in the code below.

Wq.db.rest makes it easier to build REST-full APIs that can serve as whole web pages. Despite having a REST interface in name only, wq.db.rest is meant to be used as the primary controller in a web application rather than an additional API. You don't need to include the entire module to integrate wq.db.rest that you find useful.

And then we can use it to register a model corresponding to the router that we wanted to integrate

DRF-Extension

DRF-extension is another collection of custom extensions for Django REST Framework that can be used for nested routing and also DetailSerializerMixin, Caching, Conditional requests, Bulk operations, etc.

We need to first install it

The package DRF-extension contains some functions that are useful for nesting routes, the two most commonly used of those are ExtendedSimpleRouter which is imported from rest_framework_extensions.routers and NestedViewSetMixin imported from rest_framework_extensions.mixins.

We can implement this in our code as shown below.

And for the NestedViewSetMixin, we can

Advanced

You need a custom serializer if you want hyperlinks for nested relations and if you want a little bit more control over the fields displayed for the nested relations while looking at the parent, you need a custom serializer using NestedHyperlinkedModelSerializer which is imported from rest_framework_nested.relations.

This can be implemented in the code as shown below,

Infinite-Depth Nesting

For nesting the router at multi-levels, we can use the concept of infinite-depth nesting to nest routers as deep as you need.

, For example,, if we want to create a two-level nested routers, as shown below

Conclusion

Let's conclude the article by summarizing it in some points.

  • Using the concept of a Nested router we can easily create routes like /api/students/{class}/sections and /api/students/{class}/sections/{section_id} as explained in the article.
  • We can map the URL using SimpleRouter() and as an alternative, we can use include to include an URL.
  • Additionally, we have a default API root view, which, like SimpleRouter, returns a response containing links to all the list views.
  • To achieve specific requirements, we can use custom routers that accept url, prefix , lookup , and trailing_slash which makes it more feasible, this can also be further modified.
  • In the Django Rest Framework, we can utilize a third-party package called drf-nested-routers, which seeks to offer routers and fields for creating nested resources.
  • Also, we have ModelRouter wq.db.rest, a collection of Python modules that can be used to create dependable, adaptable schemas, and REST APIs that can be used to create field data collection applications that are capable of making small adjustments.
  • Another set of unique extensions for the Django REST Framework is found in the DRF-extension package named rest_framework_extensions.routers, which may be used for nested routing, DetailSerializerMixin, Caching, Conditional requests, Bulk operations, etc.
  • We use NestedHyperlinkedModelSerializer which is imported from rest_framework_nested.relations that is used to create hyperlinks for nested relations.
  • We can leverage the idea of infinite-depth nesting to nest routers as deeply as necessary for multi-level nesting.