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
|
||||
from collections import OrderedDict, namedtuple
|
||||
from importlib import import_module
|
||||
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.urls import NoReverseMatch, re_path
|
||||
|
@ -49,6 +50,20 @@ class BaseRouter:
|
|||
def __init__(self):
|
||||
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):
|
||||
if basename is None:
|
||||
basename = self.get_default_basename(viewset)
|
||||
|
@ -58,6 +73,40 @@ class BaseRouter:
|
|||
if hasattr(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):
|
||||
"""
|
||||
If `basename` is not specified, attempt to automatically determine
|
||||
|
@ -78,6 +127,9 @@ class BaseRouter:
|
|||
return self._urls
|
||||
|
||||
|
||||
include = BaseRouter._include
|
||||
|
||||
|
||||
class SimpleRouter(BaseRouter):
|
||||
|
||||
routes = [
|
||||
|
|
Loading…
Reference in New Issue
Block a user