mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-27 16:40:03 +03:00
feat(routers): add .extend method to BaseRouter and include function
the .extend method allow to extend the routes of the current router with router from other router and a optional new prefix the include function allow to include a router without manually importing it. This is useful when importing multiple routers just for using the .extend method but nothing else
This commit is contained in:
parent
3db8877889
commit
34a93e6a50
|
@ -15,6 +15,7 @@ For example, you might have a `urls.py` that looks something like this:
|
||||||
"""
|
"""
|
||||||
import itertools
|
import itertools
|
||||||
from collections import OrderedDict, namedtuple
|
from collections import OrderedDict, namedtuple
|
||||||
|
from importlib import import_module
|
||||||
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.urls import NoReverseMatch, re_path
|
from django.urls import NoReverseMatch, re_path
|
||||||
|
@ -49,6 +50,20 @@ class BaseRouter:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.registry = []
|
self.registry = []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _include(cls, module, router_name="router"):
|
||||||
|
"""
|
||||||
|
Allow to import router object from another app
|
||||||
|
"""
|
||||||
|
router_module = import_module(module)
|
||||||
|
|
||||||
|
router = getattr(router_module, router_name)
|
||||||
|
|
||||||
|
if not isinstance(router, cls):
|
||||||
|
raise ValueError("The router should be an instance (direct or indirect) of BaseRouter")
|
||||||
|
|
||||||
|
return router
|
||||||
|
|
||||||
def register(self, prefix, viewset, basename=None):
|
def register(self, prefix, viewset, basename=None):
|
||||||
if basename is None:
|
if basename is None:
|
||||||
basename = self.get_default_basename(viewset)
|
basename = self.get_default_basename(viewset)
|
||||||
|
@ -58,6 +73,40 @@ class BaseRouter:
|
||||||
if hasattr(self, '_urls'):
|
if hasattr(self, '_urls'):
|
||||||
del self._urls
|
del self._urls
|
||||||
|
|
||||||
|
def extend(self, prefix, router):
|
||||||
|
"""
|
||||||
|
Extend the routes with url routes from the router of the module passed.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
from django.urls import path, include
|
||||||
|
from rest_framework import routers
|
||||||
|
|
||||||
|
router = routers.DefaultRouter()
|
||||||
|
|
||||||
|
router.extend('products', routers.include('project.products.urls')) # using include
|
||||||
|
|
||||||
|
from .users.urls import router as users_router
|
||||||
|
router.extend('users', users_router) # manually importing the router
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("api/", include(router.urls))
|
||||||
|
]
|
||||||
|
|
||||||
|
You can avoid naming collisions with `django.urls` include function using named imports
|
||||||
|
or importing the whole routers module:
|
||||||
|
>>> from rest_framework.routers import include as router_include
|
||||||
|
>>> from rest_framework import routers
|
||||||
|
"""
|
||||||
|
if not prefix.endswith("/"):
|
||||||
|
# TODO: warn or not the user to put an ending forward slash
|
||||||
|
prefix += "/"
|
||||||
|
|
||||||
|
for old_prefix, viewset, basename in router.registry:
|
||||||
|
new_prefix = prefix + old_prefix
|
||||||
|
|
||||||
|
self.register(new_prefix, viewset, basename)
|
||||||
|
|
||||||
def get_default_basename(self, viewset):
|
def get_default_basename(self, viewset):
|
||||||
"""
|
"""
|
||||||
If `basename` is not specified, attempt to automatically determine
|
If `basename` is not specified, attempt to automatically determine
|
||||||
|
@ -78,6 +127,9 @@ class BaseRouter:
|
||||||
return self._urls
|
return self._urls
|
||||||
|
|
||||||
|
|
||||||
|
include = BaseRouter._include
|
||||||
|
|
||||||
|
|
||||||
class SimpleRouter(BaseRouter):
|
class SimpleRouter(BaseRouter):
|
||||||
|
|
||||||
routes = [
|
routes = [
|
||||||
|
|
Loading…
Reference in New Issue
Block a user