Last edited 2023-09-23 17:07:56.401859+00:00


Parameters

Query Strings

You can add a query string parameter to your route via the query decorator:

from view import new_app, query

app = new_app()

@app.get("/hello")
@query("name", str)
async def hello(name: str):
    return p(f"Hello, {name}")

app.run()

The first argument is the name of the parameter in the query string, not the argument name, and the second argument is the type that it should take.

Body

Bodies work the exact same way as queries, but with the body decorator instead:

@app.get("/goodbye")
@body("name", str)
async def goodbye(name: str):
    return p(f"Bye, {name}")

Warning

As of now, only bodies sent in JSON are supported.

From App

In a case where you have direct access to your App instance (i.e. in manual loading), you don't have to even use body and query, and instead use the app methods instead:

@app.get("/hello")
@app.query("name", str)
async def hello(name: str):
    return f"hello, {name}"

app.query and app.body work exactly the same as @query and @body.

Path

Path parameters are even simpler, just wrap a route part in brackets, like so:

@app.get("/hello/{name}")
async def hello(name: str):
    return p(f"Your name is: {name}")

Now in the browser, if you were to go to /hello/world, the name parameter above would be world.

Here's a more complicated example:

@app.get("/auth/{user_id}/something/{token}")
async def token(user_id: str, token: str):
    # ...
    return p("Successfully authorized!")

Danger

This is extremely buggy and not yet recommended for general use.

Type Validation

view.py will ensure that the type sent to the server is compatible with what you passed to the decorator. For example:

@app.get("/")
@query("number", int)
async def index(number: int):
    # number will always be an int.
    # if it isn't, an error 400 is sent back to the user automatically
    return "..."

The following types are supported:

You can allow unions by just passing more parameters:

@app.get('/hello')
@query("name", str, None)
async def hello(name: str | None):
    if not name:
        return "hello world"

    return f"hello {name}"

You can pass type arguments to a dict, which are also validated by the server:

@app.get("/something")
@body("data", dict[str, int])  # typing.Dict on 3.8 and 3.9
async def something(data: dict[str, int]):
    # data will always be a dictionary of strings and integers
    return "..."

The key in a dictionary must always be str (i.e. dict[int, str] is not allowed), but the value can be any supported type (including other dictionaries!)