Skip to content

Commit

Permalink
OperationID support (#54)
Browse files Browse the repository at this point in the history
  • Loading branch information
vitalik committed Dec 20, 2020
1 parent 1c1d036 commit ec6ff85
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 2 deletions.
36 changes: 35 additions & 1 deletion docs/docs/tutorial/operation_params.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,45 @@ def create_order(request, order: Order):
![Summary`](../img/operation_description_docstring.png)


## OpenAPI operationId

OpenAPI `operationId` is an optional unique string used to identify an operation. If provided, these IDs must be unique among all operations described in your API.

By default Django Ninja sets it to `module name` + `function name`

if you want ot set it individually for each operation use `operation_id` argument:

```Python hl_lines="2"
...
@api.post("/tasks", operation_id="create_task")
def new_task(request):
...
```

And if you want ot override global behavior - you can inherit NinjaAPI instance and override `get_openapi_operation_id` method

it will be called to each operation, that you defined, so you can set your custom naming logic

```Python hl_lines="5 6 7 9"
from ninja import NinjaAPI

class MySuperApi(NinjaAPI):

def get_openapi_operation_id(self, operation):
# here you can access operation ( .path , .view_func, etc)
return ...

api = MySuperApi()

@api.get(...)
...
```



## Deprecating Operation

If you need to mark an operation as deprecated without removing it, use the argumetn `deprecated`:
If you need to mark an operation as deprecated without removing it, use the argument `deprecated`:

```Python hl_lines="1"
@api.post("/make-order/", deprecated=True)
Expand Down
18 changes: 18 additions & 0 deletions ninja/main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
from ninja import openapi
from ninja.openapi import get_schema
from typing import List, Optional, Tuple, Sequence, Union, Callable
from django.urls import reverse
Expand Down Expand Up @@ -45,6 +46,7 @@ def get(
*,
auth=NOT_SET,
response=None,
operation_id: Optional[str] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
tags: Optional[List[str]] = None,
Expand All @@ -54,6 +56,7 @@ def get(
path,
auth=auth is NOT_SET and self.auth or auth,
response=response,
operation_id=operation_id,
summary=summary,
description=description,
tags=tags,
Expand All @@ -66,6 +69,7 @@ def post(
*,
auth=NOT_SET,
response=None,
operation_id: Optional[str] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
tags: Optional[List[str]] = None,
Expand All @@ -75,6 +79,7 @@ def post(
path,
auth=auth is NOT_SET and self.auth or auth,
response=response,
operation_id=operation_id,
summary=summary,
description=description,
tags=tags,
Expand All @@ -87,6 +92,7 @@ def delete(
*,
auth=NOT_SET,
response=None,
operation_id: Optional[str] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
tags: Optional[List[str]] = None,
Expand All @@ -96,6 +102,7 @@ def delete(
path,
auth=auth is NOT_SET and self.auth or auth,
response=response,
operation_id=operation_id,
summary=summary,
description=description,
tags=tags,
Expand All @@ -108,6 +115,7 @@ def patch(
*,
auth=NOT_SET,
response=None,
operation_id: Optional[str] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
tags: Optional[List[str]] = None,
Expand All @@ -117,6 +125,7 @@ def patch(
path,
auth=auth is NOT_SET and self.auth or auth,
response=response,
operation_id=operation_id,
summary=summary,
description=description,
tags=tags,
Expand All @@ -129,6 +138,7 @@ def put(
*,
auth=NOT_SET,
response=None,
operation_id: Optional[str] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
tags: Optional[List[str]] = None,
Expand All @@ -138,6 +148,7 @@ def put(
path,
auth=auth is NOT_SET and self.auth or auth,
response=response,
operation_id=operation_id,
summary=summary,
description=description,
tags=tags,
Expand All @@ -151,6 +162,7 @@ def api_operation(
*,
auth=NOT_SET,
response=None,
operation_id: Optional[str] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
tags: Optional[List[str]] = None,
Expand All @@ -161,6 +173,7 @@ def api_operation(
path,
auth=auth is NOT_SET and self.auth or auth,
response=response,
operation_id=operation_id,
summary=summary,
description=description,
tags=tags,
Expand Down Expand Up @@ -200,6 +213,11 @@ def get_openapi_schema(self, path_prefix=None):
path_prefix = self.root_path
return get_schema(api=self, path_prefix=path_prefix)

def get_openapi_operation_id(self, operation: "Operation"):
name = operation.view_func.__name__
module = operation.view_func.__module__
return (module + "_" + name).replace(".", "_")

def _validate(self):
from ninja.security import APIKeyCookie

Expand Down
2 changes: 2 additions & 0 deletions ninja/openapi/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ def methods(self, operations: list):
return result

def operation_details(self, operation: Operation):
op_id = operation.operation_id or self.api.get_openapi_operation_id(operation)
result = {
"operationId": op_id,
"summary": operation.summary,
"parameters": self.operation_parameters(operation),
"responses": self.responses(operation),
Expand Down
5 changes: 5 additions & 0 deletions ninja/operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def __init__(
*,
auth: Optional[Union[Sequence[Callable], Callable, object]] = NOT_SET,
response: Any = None,
operation_id: Optional[str] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
tags: Optional[List[str]] = None,
Expand All @@ -42,6 +43,7 @@ def __init__(
else:
self.response_model = self._create_response_model(response)

self.operation_id = operation_id
self.summary = summary or self.view_func.__name__.title().replace("_", " ")
self.description = description or self.signature.docstring
self.tags = tags
Expand Down Expand Up @@ -171,6 +173,7 @@ def add(
*,
auth: Optional[Union[Sequence[Callable], Callable, object]] = NOT_SET,
response=None,
operation_id: Optional[str] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
tags: Optional[List[str]] = None,
Expand All @@ -184,6 +187,7 @@ def add(
view_func,
auth=auth,
response=response,
operation_id=operation_id,
summary=summary,
description=description,
tags=tags,
Expand All @@ -196,6 +200,7 @@ def add(
view_func,
auth=auth,
response=response,
operation_id=operation_id,
summary=summary,
description=description,
tags=tags,
Expand Down
14 changes: 14 additions & 0 deletions ninja/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def get(
*,
auth=NOT_SET,
response=None,
operation_id: Optional[str] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
tags: Optional[List[str]] = None,
Expand All @@ -30,6 +31,7 @@ def get(
path,
auth=auth,
response=response,
operation_id=operation_id,
summary=summary,
description=description,
tags=tags,
Expand All @@ -42,6 +44,7 @@ def post(
*,
auth=NOT_SET,
response=None,
operation_id: Optional[str] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
tags: Optional[List[str]] = None,
Expand All @@ -52,6 +55,7 @@ def post(
path,
auth=auth,
response=response,
operation_id=operation_id,
summary=summary,
description=description,
tags=tags,
Expand All @@ -64,6 +68,7 @@ def delete(
*,
auth=NOT_SET,
response=None,
operation_id: Optional[str] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
tags: Optional[List[str]] = None,
Expand All @@ -74,6 +79,7 @@ def delete(
path,
auth=auth,
response=response,
operation_id=operation_id,
summary=summary,
description=description,
tags=tags,
Expand All @@ -86,6 +92,7 @@ def patch(
*,
auth=NOT_SET,
response=None,
operation_id: Optional[str] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
tags: Optional[List[str]] = None,
Expand All @@ -96,6 +103,7 @@ def patch(
path,
auth=auth,
response=response,
operation_id=operation_id,
summary=summary,
description=description,
tags=tags,
Expand All @@ -108,6 +116,7 @@ def put(
*,
auth=NOT_SET,
response=None,
operation_id: Optional[str] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
tags: Optional[List[str]] = None,
Expand All @@ -118,6 +127,7 @@ def put(
path,
auth=auth,
response=response,
operation_id=operation_id,
summary=summary,
description=description,
tags=tags,
Expand All @@ -131,6 +141,7 @@ def api_operation(
*,
auth=NOT_SET,
response=None,
operation_id: Optional[str] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
tags: Optional[List[str]] = None,
Expand All @@ -143,6 +154,7 @@ def decorator(view_func):
view_func,
auth=auth,
response=response,
operation_id=operation_id,
summary=summary,
description=description,
tags=tags,
Expand All @@ -160,6 +172,7 @@ def add_api_operation(
*,
auth=NOT_SET,
response=None,
operation_id: Optional[str] = None,
summary: Optional[str] = None,
description: Optional[str] = None,
tags: Optional[List[str]] = None,
Expand All @@ -176,6 +189,7 @@ def add_api_operation(
view_func=view_func,
auth=auth,
response=response,
operation_id=operation_id,
summary=summary,
description=description,
tags=tags,
Expand Down
7 changes: 6 additions & 1 deletion tests/test_openapi_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
api = NinjaAPI()


@api.get("/operation1")
@api.get("/operation1", operation_id="my_id")
def operation_1(request):
"""
This will be in description
Expand Down Expand Up @@ -39,6 +39,11 @@ def test_schema():
op4 = schema["paths"]["/api/operation4"]["get"]

pprint(op1)
assert op1["operationId"] == "my_id"
assert op2["operationId"] == "test_openapi_params_operation2"
assert op3["operationId"] == "test_openapi_params_operation3"
assert op4["operationId"] == "test_openapi_params_operation4"

assert op1["summary"] == "Operation 1"
assert op2["summary"] == "Operation2"
assert op3["summary"] == "Summary from argument"
Expand Down

0 comments on commit ec6ff85

Please sign in to comment.