Path Parameters¶
You can declare path "parameters" with the same syntax used by Python format-strings which is similar to OpenAPI path parameters
# project_name/apps/items/controllers.py
from ellar.common import get, Controller, ControllerBase
@Controller
class ItemsController(ControllerBase):
@get("/{item_id}")
def read_item(self, item_id):
return {"item_id": item_id}
The value of the path parameter item_id
will be passed to your function as the argument item_id
.
So, if you run this example and go to http://localhost:8000/items/foo, you will see this response:
{
"item_id":"foo"
}
Path parameters with types¶
You can declare the type of path parameter in the function using standard Python type annotations:
# project_name/apps/items/controllers.py
from ellar.common import get, Controller, ControllerBase
@Controller
class ItemsController(ControllerBase):
@get("/items/{item_id}")
def read_item(self, item_id: int):
return {"item_id": item_id}
In this case,item_id
is declared to be an int
. This will give you editor and linter support for error checks, completion, etc.
If you run this in your browser with http://localhost:8000/api/items/3, you will see this response:
{
"item_id":3
}
Tip
Notice that the value your function received (and returned) is 3, as a Python int
- not a string "3"
. So, with just that type declaration, Ellar gives you automatic request "parsing" and validation.
Data validation¶
On the other hand, if you go to the browser at http://localhost:8000/items/foo, you will see an HTTP error like this:
{
"detail": [
{
"loc": [
"path",
"item_id"
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}
item_id
had a value of "foo"
, which is not an int
. The same error would appear if you provided a float
instead of an int
, as in: http://localhost:8000/items/4.2
Path Converters¶
You can use Starlette Path Converters to help parse the path:
# project_name/apps/items/controllers.py
from ellar.common import get, Controller, ControllerBase
@Controller
class ItemsController(ControllerBase):
@get("/{item_id:int}")
def read_item(self, item_id):
return {"item_id": item_id}
In this case,item_id
will be parsed as an int
. If item_id
is not a valid int
, the url will not match. (e.g. if no other path matches, a 404 Not Found will be returned)
Tip
Notice that, since Ellar uses a default type of str
for unannotated parameters, the value the function above received (and returned) is "3"
, as a Python str
- not an integer 3. To receive an int
, simply declare item_id
as an int
type annotation in the function definition as normal:
...
@get("/items/{int:item_id}")
def read_item(self, item_id:int):
return {"item_id": item_id}
Path params with slashes¶
Starlette path
converter allows you to handle path-like parameters:
For example, lets another route handler some_view
and give it a path /dir/{value:path}
. What this means is that the parameter is value
, and the last part, :path
, tells it that the parameter should match any path.
# project_name/apps/items/controllers.py
from ellar.common import get, Controller, ControllerBase
@Controller
class ItemsController(ControllerBase):
@get('/dir/{value:path}')
def some_view(self, value: str):
return value
value
will be equal to "some/path/with-slashes"
Multiple parameters¶
You can pass as many variables as you want into path
, just remember to have unique names and don't forget to use the same names in the function arguments.
# project_name/apps/items/controllers.py
from ellar.common import get, Controller, ControllerBase
@Controller
class ItemsController(ControllerBase):
@get("/events/{year}/{month}/{day}")
def events(self, year: int, month: int, day: int):
return {"date": [year, month, day]}
Using Schema¶
You can also use Schema to encapsulate path parameters that depend on each other (and validate them as a group):
# project_name/apps/items/controllers.py
import datetime
from ellar.common import Serializer, get, Controller, Path, ControllerBase
class PathDate(Serializer):
year: int
month: int
day: int
def value(self):
return datetime.date(self.year, self.month, self.day)
@Controller
class ItemsController(ControllerBase):
@get("/events/{year}/{month}/{day}")
def events(self, date: PathDate = Path()):
return {"date": date.value()}
Note
Notice that here we used a Path
source hint to let Ellar know that this schema will be applied to path parameters.
Documentation¶
Now, when you open your browser at http://localhost:8000/docs, you will see the automatic, interactive, API documentation.
Using Enum¶
If you have a path operation that receives a path parameter, but you want the possible valid path parameter values to be predefined, you can use a standard Python Enum
.
For an example:
# project_name/apps/items/controllers.py
from ellar.common import get, Controller, ControllerBase
from enum import Enum
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
@Controller
class ItemsController(ControllerBase):
@get("/models/{model_name}")
async def get_model(self, model_name: ModelName):
if model_name is ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
Check the docs¶
Because the available values for the path parameter are predefined, the interactive docs can show them nicely: