Recap and assembling the final application#
So far we have looked at the different parts of the application in isolation, but now it’s time to put them all together and assemble a complete application.
Final application#
app.py# 1from dataclasses import dataclass
2from typing import List, Optional
3
4from litestar import Litestar, get, post, put
5from litestar.exceptions import NotFoundException
6from litestar.params import FromPath, FromQuery
7
8
9@dataclass
10class TodoItem:
11 title: str
12 done: bool
13
14
15TODO_LIST: List[TodoItem] = [
16 TodoItem(title="Start writing TODO list", done=True),
17 TodoItem(title="???", done=False),
18 TodoItem(title="Profit", done=False),
19]
20
21
22def get_todo_by_title(todo_name: str) -> TodoItem:
23 for item in TODO_LIST:
24 if item.title == todo_name:
25 return item
26 raise NotFoundException(detail=f"TODO {todo_name!r} not found")
27
28
29@get("/")
30async def get_list(done: FromQuery[Optional[bool]] = None) -> List[TodoItem]:
31 if done is None:
32 return TODO_LIST
33 return [item for item in TODO_LIST if item.done == done]
34
35
36@post("/")
37async def add_item(data: TodoItem) -> List[TodoItem]:
38 TODO_LIST.append(data)
39 return TODO_LIST
40
41
42@put("/{item_title:str}")
43async def update_item(item_title: FromPath[str], data: TodoItem) -> List[TodoItem]:
44 todo_item = get_todo_by_title(item_title)
45 todo_item.title = data.title
46 todo_item.done = data.done
47 return TODO_LIST
48
49
50app = Litestar([get_list, add_item, update_item])
app.py# 1from dataclasses import dataclass
2from typing import Optional
3
4from litestar import Litestar, get, post, put
5from litestar.exceptions import NotFoundException
6from litestar.params import FromPath, FromQuery
7
8
9@dataclass
10class TodoItem:
11 title: str
12 done: bool
13
14
15TODO_LIST: list[TodoItem] = [
16 TodoItem(title="Start writing TODO list", done=True),
17 TodoItem(title="???", done=False),
18 TodoItem(title="Profit", done=False),
19]
20
21
22def get_todo_by_title(todo_name: str) -> TodoItem:
23 for item in TODO_LIST:
24 if item.title == todo_name:
25 return item
26 raise NotFoundException(detail=f"TODO {todo_name!r} not found")
27
28
29@get("/")
30async def get_list(done: FromQuery[Optional[bool]] = None) -> list[TodoItem]:
31 if done is None:
32 return TODO_LIST
33 return [item for item in TODO_LIST if item.done == done]
34
35
36@post("/")
37async def add_item(data: TodoItem) -> list[TodoItem]:
38 TODO_LIST.append(data)
39 return TODO_LIST
40
41
42@put("/{item_title:str}")
43async def update_item(item_title: FromPath[str], data: TodoItem) -> list[TodoItem]:
44 todo_item = get_todo_by_title(item_title)
45 todo_item.title = data.title
46 todo_item.done = data.done
47 return TODO_LIST
48
49
50app = Litestar([get_list, add_item, update_item])
app.py# 1from dataclasses import dataclass
2
3from litestar import Litestar, get, post, put
4from litestar.exceptions import NotFoundException
5from litestar.params import FromPath, FromQuery
6
7
8@dataclass
9class TodoItem:
10 title: str
11 done: bool
12
13
14TODO_LIST: list[TodoItem] = [
15 TodoItem(title="Start writing TODO list", done=True),
16 TodoItem(title="???", done=False),
17 TodoItem(title="Profit", done=False),
18]
19
20
21def get_todo_by_title(todo_name: str) -> TodoItem:
22 for item in TODO_LIST:
23 if item.title == todo_name:
24 return item
25 raise NotFoundException(detail=f"TODO {todo_name!r} not found")
26
27
28@get("/")
29async def get_list(done: FromQuery[bool | None] = None) -> list[TodoItem]:
30 if done is None:
31 return TODO_LIST
32 return [item for item in TODO_LIST if item.done == done]
33
34
35@post("/")
36async def add_item(data: TodoItem) -> list[TodoItem]:
37 TODO_LIST.append(data)
38 return TODO_LIST
39
40
41@put("/{item_title:str}")
42async def update_item(item_title: FromPath[str], data: TodoItem) -> list[TodoItem]:
43 todo_item = get_todo_by_title(item_title)
44 todo_item.title = data.title
45 todo_item.done = data.done
46 return TODO_LIST
47
48
49app = Litestar([get_list, add_item, update_item])
Recap#
app.py#29@get("/")
30async def get_list(done: FromQuery[Optional[bool]] = None) -> List[TodoItem]:
31 if done is None:
32 return TODO_LIST
33 return [item for item in TODO_LIST if item.done == done]
A route handler set up with get("/") responds to GET requests and returns a list
of all items on our TODO list. The optional query parameter done allows filtering
the items by status. It is declared as FromQuery[bool | None]: the
FromQuery marker tells Litestar to read the value from the URL query
string, the inner bool triggers conversion, and wrapping it in
Optional (combined with the = None default) makes it
optional.
app.py#36@post("/")
37async def add_item(data: TodoItem) -> List[TodoItem]:
38 TODO_LIST.append(data)
39 return TODO_LIST
A route handler set up with post("/") responds to POST requests and adds an item
to the TODO list. The data for the new item is received via the request data, which the
route handler accesses by specifying the data parameter. The type annotation of
TodoItem means the request data will parsed as JSON, which is then used to create an
instance of the TodoItem dataclass, which - finally - gets passed into the function.
app.py#42@put("/{item_title:str}")
43async def update_item(item_title: FromPath[str], data: TodoItem) -> List[TodoItem]:
44 todo_item = get_todo_by_title(item_title)
45 todo_item.title = data.title
46 todo_item.done = data.done
47 return TODO_LIST
A route handler set up with put("/{item_title:str}"), making use of a path parameter,
responds to PUT requests on the path /some todo title, where some todo title
is the title of the TodoItem you wish to update. The handler declares
item_title: FromPath[str] to receive the captured value; the FromPath
marker tells Litestar this kwarg comes from the URL path, and the matching name
(item_title) lines it up with the {item_title:str} slot. The :str suffix in the
path pattern means the value is treated as a string. Additionally, this route handler
receives data of a TodoItem the same way as the POST handler.
app.py#50app = Litestar([get_list, add_item, update_item])
An instance of Litestar is created, including the previously defined route handlers.
This app can now be served using an ASGI server like
uvicorn, which can be conveniently done using Litestar’s
CLI by executing the litestar run command.
Next steps#
This tutorial covered some of the fundamental concepts of Litestar. For a more in-depth explanation of these topics, refer to the Usage Guide.