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#
1from dataclasses import dataclass
2from typing import List, Optional
3
4from litestar import Litestar, get, post, put
5from litestar.exceptions import NotFoundException
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) -> 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: Optional[bool] = 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: 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])
1from dataclasses import dataclass
2from typing import Optional
3
4from litestar import Litestar, get, post, put
5from litestar.exceptions import NotFoundException
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) -> 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: Optional[bool] = 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: 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])
1from dataclasses import dataclass
2
3from litestar import Litestar, get, post, put
4from litestar.exceptions import NotFoundException
5
6
7@dataclass
8class TodoItem:
9 title: str
10 done: bool
11
12
13TODO_LIST: list[TodoItem] = [
14 TodoItem(title="Start writing TODO list", done=True),
15 TodoItem(title="???", done=False),
16 TodoItem(title="Profit", done=False),
17]
18
19
20def get_todo_by_title(todo_name) -> TodoItem:
21 for item in TODO_LIST:
22 if item.title == todo_name:
23 return item
24 raise NotFoundException(detail=f"TODO {todo_name!r} not found")
25
26
27@get("/")
28async def get_list(done: bool | None = None) -> list[TodoItem]:
29 if done is None:
30 return TODO_LIST
31 return [item for item in TODO_LIST if item.done == done]
32
33
34@post("/")
35async def add_item(data: TodoItem) -> list[TodoItem]:
36 TODO_LIST.append(data)
37 return TODO_LIST
38
39
40@put("/{item_title:str}")
41async def update_item(item_title: str, data: TodoItem) -> list[TodoItem]:
42 todo_item = get_todo_by_title(item_title)
43 todo_item.title = data.title
44 todo_item.done = data.done
45 return TODO_LIST
46
47
48app = Litestar([get_list, add_item, update_item])
Recap#
28@get("/")
29async def get_list(done: Optional[bool] = None) -> List[TodoItem]:
30 if done is None:
31 return TODO_LIST
32 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. The type annotation of bool
converts the query parameter into
a bool
, and wrapping it in Optional
makes it optional.
35@post("/")
36async def add_item(data: TodoItem) -> List[TodoItem]:
37 TODO_LIST.append(data)
38 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.
41@put("/{item_title:str}")
42async def update_item(item_title: 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
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. It receives the value of the path
parameter via the function parameter of the same name item_title
. The :str
suffix in the path parameter means it will be treated as a string. Additionally, this
route handler receives data of a TodoItem
the same way as the POST
handler.
49app = 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.