diff --git a/ninja/main.py b/ninja/main.py index 5902e2759..321e992ee 100644 --- a/ninja/main.py +++ b/ninja/main.py @@ -406,10 +406,9 @@ def _get_urls(self) -> List[Union[URLResolver, URLPattern]]: result.append(get_root_url(self)) return result - @property - def root_path(self) -> str: + def get_root_path(self, path_params: DictStrAny) -> str: name = f"{self.urls_namespace}:api-root" - return reverse(name) + return reverse(name, kwargs=path_params) def create_response( self, @@ -441,9 +440,14 @@ def create_temporal_response(self, request: HttpRequest) -> HttpResponse: def get_content_type(self) -> str: return "{}; charset={}".format(self.renderer.media_type, self.renderer.charset) - def get_openapi_schema(self, path_prefix: Optional[str] = None) -> OpenAPISchema: + def get_openapi_schema( + self, + *, + path_prefix: Optional[str] = None, + path_params: Optional[DictStrAny] = None, + ) -> OpenAPISchema: if path_prefix is None: - path_prefix = self.root_path + path_prefix = self.get_root_path(path_params or {}) return get_schema(api=self, path_prefix=path_prefix) def get_openapi_operation_id(self, operation: "Operation") -> str: diff --git a/ninja/openapi/docs.py b/ninja/openapi/docs.py index cc02b0703..596885d7a 100644 --- a/ninja/openapi/docs.py +++ b/ninja/openapi/docs.py @@ -1,7 +1,7 @@ import json import os from abc import ABC, abstractmethod -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING, Any, Optional from django.conf import settings from django.http import HttpRequest, HttpResponse @@ -20,11 +20,13 @@ class DocsBase(ABC): @abstractmethod - def render_page(self, request: HttpRequest, api: "NinjaAPI") -> HttpResponse: + def render_page( + self, request: HttpRequest, api: "NinjaAPI", **kwargs: Any + ) -> HttpResponse: pass # pragma: no cover - def get_openapi_url(self, api: "NinjaAPI") -> str: - return reverse(f"{api.urls_namespace}:openapi-json") + def get_openapi_url(self, api: "NinjaAPI", path_params: DictStrAny) -> str: + return reverse(f"{api.urls_namespace}:openapi-json", kwargs=path_params) class Swagger(DocsBase): @@ -41,8 +43,10 @@ def __init__(self, settings: Optional[DictStrAny] = None): if settings: self.settings.update(settings) - def render_page(self, request: HttpRequest, api: "NinjaAPI") -> HttpResponse: - self.settings["url"] = self.get_openapi_url(api) + def render_page( + self, request: HttpRequest, api: "NinjaAPI", **kwargs: Any + ) -> HttpResponse: + self.settings["url"] = self.get_openapi_url(api, kwargs) context = { "swagger_settings": json.dumps(self.settings, indent=1), "api": api, @@ -62,10 +66,12 @@ def __init__(self, settings: Optional[DictStrAny] = None): if settings: self.settings.update(settings) - def render_page(self, request: HttpRequest, api: "NinjaAPI") -> HttpResponse: + def render_page( + self, request: HttpRequest, api: "NinjaAPI", **kwargs: Any + ) -> HttpResponse: context = { "redoc_settings": json.dumps(self.settings, indent=1), - "openapi_json_url": self.get_openapi_url(api), + "openapi_json_url": self.get_openapi_url(api, kwargs), "api": api, } return render_template(request, self.template, self.template_cdn, context) diff --git a/ninja/openapi/views.py b/ninja/openapi/views.py index f9f70fff6..d2c6660f5 100644 --- a/ninja/openapi/views.py +++ b/ninja/openapi/views.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, NoReturn +from typing import TYPE_CHECKING, Any, NoReturn from django.http import Http404, HttpRequest, HttpResponse @@ -10,17 +10,17 @@ from ninja import NinjaAPI # pragma: no cover -def default_home(request: HttpRequest, api: "NinjaAPI") -> NoReturn: +def default_home(request: HttpRequest, api: "NinjaAPI", **kwargs: Any) -> NoReturn: "This view is mainly needed to determine the full path for API operations" docs_url = f"{request.path}{api.docs_url}".replace("//", "/") raise Http404(f"docs_url = {docs_url}") -def openapi_json(request: HttpRequest, api: "NinjaAPI") -> HttpResponse: - schema = api.get_openapi_schema() +def openapi_json(request: HttpRequest, api: "NinjaAPI", **kwargs: Any) -> HttpResponse: + schema = api.get_openapi_schema(path_params=kwargs) return Response(schema) -def openapi_view(request: HttpRequest, api: "NinjaAPI") -> HttpResponse: +def openapi_view(request: HttpRequest, api: "NinjaAPI", **kwargs: Any) -> HttpResponse: docs: DocsBase = api.docs - return docs.render_page(request, api) + return docs.render_page(request, api, **kwargs) diff --git a/tests/test_docs/test_path.py b/tests/test_docs/test_path.py index 853465264..6f33e7c17 100644 --- a/tests/test_docs/test_path.py +++ b/tests/test_docs/test_path.py @@ -28,7 +28,7 @@ def test_examples(): response = client.get("/events/2020/1/1") assert response.json() == {"date": "2020-01-01"} - schema = api.get_openapi_schema("") + schema = api.get_openapi_schema(path_prefix="") events_params = schema["paths"]["/events/{year}/{month}/{day}"]["get"][ "parameters" ] diff --git a/tests/test_docs/test_query.py b/tests/test_docs/test_query.py index 5c313ac74..f2a109fe0 100644 --- a/tests/test_docs/test_query.py +++ b/tests/test_docs/test_query.py @@ -98,7 +98,7 @@ def test_examples(): } } - schema = api.get_openapi_schema("") + schema = api.get_openapi_schema(path_prefix="") params = schema["paths"]["/filter"]["get"]["parameters"] # print(params) assert params == [