]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
:pencil: Document overriding operationId for all path operations using their function...
authorSteven Kalt <SKalt@users.noreply.github.com>
Sun, 24 Nov 2019 14:00:51 +0000 (09:00 -0500)
committerSebastián Ramírez <tiangolo@gmail.com>
Sun, 24 Nov 2019 14:00:51 +0000 (15:00 +0100)
docs/src/path_operation_advanced_configuration/tutorial002.py
docs/src/path_operation_advanced_configuration/tutorial003.py
docs/src/path_operation_advanced_configuration/tutorial004.py [new file with mode: 0644]
docs/tutorial/path-operation-advanced-configuration.md
tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py
tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py
tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py [new file with mode: 0644]

index dcc358e323d4da561d37ecaac25b7775ee87c28f..3aaae9b3710c365637592a2b8d53d6ae40e70e71 100644 (file)
@@ -1,8 +1,24 @@
 from fastapi import FastAPI
+from fastapi.routing import APIRoute
 
 app = FastAPI()
 
 
-@app.get("/items/", include_in_schema=False)
+@app.get("/items/")
 async def read_items():
     return [{"item_id": "Foo"}]
+
+
+def use_route_names_as_operation_ids(app: FastAPI) -> None:
+    """
+    Simplify operation IDs so that generated API clients have simpler function
+    names.
+
+    Should be called only after all routes have been added.
+    """
+    for route in app.routes:
+        if isinstance(route, APIRoute):
+            route.operation_id = route.name  # in this case, 'read_items'
+
+
+use_route_names_as_operation_ids(app)
index 36bf02b1133f50bd6890022e2a8fd5f4247b6d32..dcc358e323d4da561d37ecaac25b7775ee87c28f 100644 (file)
@@ -1,30 +1,8 @@
-from typing import Set
-
 from fastapi import FastAPI
-from pydantic import BaseModel
 
 app = FastAPI()
 
 
-class Item(BaseModel):
-    name: str
-    description: str = None
-    price: float
-    tax: float = None
-    tags: Set[str] = []
-
-
-@app.post("/items/", response_model=Item, summary="Create an item")
-async def create_item(*, item: Item):
-    """
-    Create an item with all the information:
-
-    - **name**: each item must have a name
-    - **description**: a long description
-    - **price**: required
-    - **tax**: if the item doesn't have tax, you can omit this
-    - **tags**: a set of unique tag strings for this item
-    \f
-    :param item: User input.
-    """
-    return item
+@app.get("/items/", include_in_schema=False)
+async def read_items():
+    return [{"item_id": "Foo"}]
diff --git a/docs/src/path_operation_advanced_configuration/tutorial004.py b/docs/src/path_operation_advanced_configuration/tutorial004.py
new file mode 100644 (file)
index 0000000..36bf02b
--- /dev/null
@@ -0,0 +1,30 @@
+from typing import Set
+
+from fastapi import FastAPI
+from pydantic import BaseModel
+
+app = FastAPI()
+
+
+class Item(BaseModel):
+    name: str
+    description: str = None
+    price: float
+    tax: float = None
+    tags: Set[str] = []
+
+
+@app.post("/items/", response_model=Item, summary="Create an item")
+async def create_item(*, item: Item):
+    """
+    Create an item with all the information:
+
+    - **name**: each item must have a name
+    - **description**: a long description
+    - **price**: required
+    - **tax**: if the item doesn't have tax, you can omit this
+    - **tags**: a set of unique tag strings for this item
+    \f
+    :param item: User input.
+    """
+    return item
index b316159c5fae0ff2c56f2ca84651ff20350b4cf8..7e17bcd1b3cc854cc4219b348fcde770f1ba3dd6 100644 (file)
@@ -11,12 +11,30 @@ You would have to make sure that it is unique for each operation.
 {!./src/path_operation_advanced_configuration/tutorial001.py!}
 ```
 
+### Using the *path operation function* name as the operationId
+
+If you want to use your APIs' function names as `operationId`s, you can iterate over all of them and override each *path operation's* `operation_id` using their `APIRoute.name`.
+
+You should do it after adding all your *path operations*.
+
+```Python hl_lines="2 12 13 14 15 16 17 18 19 20 21 24"
+{!./src/path_operation_advanced_configuration/tutorial002.py!}
+```
+
+!!! tip
+    If you manually call `app.openapi()`, you should update the `operationId`s before that.
+
+!!! warning
+    If you do this, you have to make sure each one of your *path operation functions* has a unique name.
+
+    Even if they are in different modules (Python files).
+
 ## Exclude from OpenAPI
 
 To exclude a path operation from the generated OpenAPI schema (and thus, from the automatic documentation systems), use the parameter `include_in_schema` and set it to `False`;
 
 ```Python hl_lines="6"
-{!./src/path_operation_advanced_configuration/tutorial002.py!}
+{!./src/path_operation_advanced_configuration/tutorial003.py!}
 ```
 
 ## Advanced description from docstring
@@ -28,5 +46,5 @@ Adding an `\f` (an escaped "form feed" character) causes **FastAPI** to truncate
 It won't show up in the documentation, but other tools (such as Sphinx) will be able to use the rest.
 
 ```Python hl_lines="19 20 21 22 23 24 25 26 27 28 29"
-{!./src/path_operation_advanced_configuration/tutorial003.py!}
+{!./src/path_operation_advanced_configuration/tutorial004.py!}
 ```
index 7818a0b966e6a9077927a9deccd75b03132817b6..0cd25c21ba5b435d454aff6dd23fe88f7d556c11 100644 (file)
@@ -7,7 +7,20 @@ client = TestClient(app)
 openapi_schema = {
     "openapi": "3.0.2",
     "info": {"title": "Fast API", "version": "0.1.0"},
-    "paths": {},
+    "paths": {
+        "/items/": {
+            "get": {
+                "responses": {
+                    "200": {
+                        "description": "Successful Response",
+                        "content": {"application/json": {"schema": {}}},
+                    }
+                },
+                "summary": "Read Items",
+                "operationId": "read_items",
+            }
+        }
+    },
 }
 
 
index 9fae3160f8ac9ede26b9df6a01d7157931c04efc..9ff0adfb97580c2d2ca30de8f3339f0cf641774a 100644 (file)
@@ -7,90 +7,7 @@ client = TestClient(app)
 openapi_schema = {
     "openapi": "3.0.2",
     "info": {"title": "Fast API", "version": "0.1.0"},
-    "paths": {
-        "/items/": {
-            "post": {
-                "responses": {
-                    "200": {
-                        "description": "Successful Response",
-                        "content": {
-                            "application/json": {
-                                "schema": {"$ref": "#/components/schemas/Item"}
-                            }
-                        },
-                    },
-                    "422": {
-                        "description": "Validation Error",
-                        "content": {
-                            "application/json": {
-                                "schema": {
-                                    "$ref": "#/components/schemas/HTTPValidationError"
-                                }
-                            }
-                        },
-                    },
-                },
-                "summary": "Create an item",
-                "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item\n",
-                "operationId": "create_item_items__post",
-                "requestBody": {
-                    "content": {
-                        "application/json": {
-                            "schema": {"$ref": "#/components/schemas/Item"}
-                        }
-                    },
-                    "required": True,
-                },
-            }
-        }
-    },
-    "components": {
-        "schemas": {
-            "Item": {
-                "title": "Item",
-                "required": ["name", "price"],
-                "type": "object",
-                "properties": {
-                    "name": {"title": "Name", "type": "string"},
-                    "price": {"title": "Price", "type": "number"},
-                    "description": {"title": "Description", "type": "string"},
-                    "tax": {"title": "Tax", "type": "number"},
-                    "tags": {
-                        "title": "Tags",
-                        "uniqueItems": True,
-                        "type": "array",
-                        "items": {"type": "string"},
-                        "default": [],
-                    },
-                },
-            },
-            "ValidationError": {
-                "title": "ValidationError",
-                "required": ["loc", "msg", "type"],
-                "type": "object",
-                "properties": {
-                    "loc": {
-                        "title": "Location",
-                        "type": "array",
-                        "items": {"type": "string"},
-                    },
-                    "msg": {"title": "Message", "type": "string"},
-                    "type": {"title": "Error Type", "type": "string"},
-                },
-            },
-            "HTTPValidationError": {
-                "title": "HTTPValidationError",
-                "type": "object",
-                "properties": {
-                    "detail": {
-                        "title": "Detail",
-                        "type": "array",
-                        "items": {"$ref": "#/components/schemas/ValidationError"},
-                    }
-                },
-            },
-        }
-    },
+    "paths": {},
 }
 
 
@@ -100,13 +17,7 @@ def test_openapi_schema():
     assert response.json() == openapi_schema
 
 
-def test_query_params_str_validations():
-    response = client.post("/items/", json={"name": "Foo", "price": 42})
+def test_get():
+    response = client.get("/items/")
     assert response.status_code == 200
-    assert response.json() == {
-        "name": "Foo",
-        "price": 42,
-        "description": None,
-        "tax": None,
-        "tags": [],
-    }
+    assert response.json() == [{"item_id": "Foo"}]
diff --git a/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py b/tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py
new file mode 100644 (file)
index 0000000..66065d8
--- /dev/null
@@ -0,0 +1,112 @@
+from starlette.testclient import TestClient
+
+from path_operation_advanced_configuration.tutorial004 import app
+
+client = TestClient(app)
+
+openapi_schema = {
+    "openapi": "3.0.2",
+    "info": {"title": "Fast API", "version": "0.1.0"},
+    "paths": {
+        "/items/": {
+            "post": {
+                "responses": {
+                    "200": {
+                        "description": "Successful Response",
+                        "content": {
+                            "application/json": {
+                                "schema": {"$ref": "#/components/schemas/Item"}
+                            }
+                        },
+                    },
+                    "422": {
+                        "description": "Validation Error",
+                        "content": {
+                            "application/json": {
+                                "schema": {
+                                    "$ref": "#/components/schemas/HTTPValidationError"
+                                }
+                            }
+                        },
+                    },
+                },
+                "summary": "Create an item",
+                "description": "Create an item with all the information:\n\n- **name**: each item must have a name\n- **description**: a long description\n- **price**: required\n- **tax**: if the item doesn't have tax, you can omit this\n- **tags**: a set of unique tag strings for this item\n",
+                "operationId": "create_item_items__post",
+                "requestBody": {
+                    "content": {
+                        "application/json": {
+                            "schema": {"$ref": "#/components/schemas/Item"}
+                        }
+                    },
+                    "required": True,
+                },
+            }
+        }
+    },
+    "components": {
+        "schemas": {
+            "Item": {
+                "title": "Item",
+                "required": ["name", "price"],
+                "type": "object",
+                "properties": {
+                    "name": {"title": "Name", "type": "string"},
+                    "price": {"title": "Price", "type": "number"},
+                    "description": {"title": "Description", "type": "string"},
+                    "tax": {"title": "Tax", "type": "number"},
+                    "tags": {
+                        "title": "Tags",
+                        "uniqueItems": True,
+                        "type": "array",
+                        "items": {"type": "string"},
+                        "default": [],
+                    },
+                },
+            },
+            "ValidationError": {
+                "title": "ValidationError",
+                "required": ["loc", "msg", "type"],
+                "type": "object",
+                "properties": {
+                    "loc": {
+                        "title": "Location",
+                        "type": "array",
+                        "items": {"type": "string"},
+                    },
+                    "msg": {"title": "Message", "type": "string"},
+                    "type": {"title": "Error Type", "type": "string"},
+                },
+            },
+            "HTTPValidationError": {
+                "title": "HTTPValidationError",
+                "type": "object",
+                "properties": {
+                    "detail": {
+                        "title": "Detail",
+                        "type": "array",
+                        "items": {"$ref": "#/components/schemas/ValidationError"},
+                    }
+                },
+            },
+        }
+    },
+}
+
+
+def test_openapi_schema():
+    response = client.get("/openapi.json")
+    assert response.status_code == 200
+    assert response.json() == openapi_schema
+
+
+def test_query_params_str_validations():
+    response = client.post("/items/", json={"name": "Foo", "price": 42})
+    assert response.status_code == 200
+    assert response.json() == {
+        "name": "Foo",
+        "price": 42,
+        "description": None,
+        "tax": None,
+        "tags": [],
+    }