■ FastAPI 클래스에서 JINJA 템플리트를 사용하는 방법을 보여준다.
▶ template/home.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta content="IE=edge" http-equiv="X-UA-Compatible" /> <meta content="width=device-width, initial-scale=1.0" name="viewport" /> <title>Packt Todo Application</title> <link crossorigin="anonymous" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" rel="stylesheet" /> <link crossorigin="anonymous" href="https://use.fontawesome.com/releases/v5.0.10/css/all.css" integrity="sha384-+d0P83n9kaQMCwj8F4RJB66tzIwOKmrdb46+porD/OvrJ+37WqIM7UoBtwHO6Nlg" rel="stylesheet" /> </head> <body> <header> <nav class="navar"> <div class="container-fluid"> <center> <h1>Packt Todo Application</h1> </center> </div> </nav> </header> <body> <div class="container-fluid"> {% block todo_container %}{% endblock %} </div> </body> </html> |
▶ template/todo.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
{% extends "home.html" %} {% block todo_container %} <main class="container"> <hr> <section class="container-fluid"> <form method="post"> <div class="col-auto"> <div class="input-group mb-3"> <input name="item" class="form-control" type="text" aria-describedby="button-addon2" aria-label="Add a todo" placeholder="Purchase Packt's Python workshop course" value="{{ item }}" /> <button id="button-addon2" class="btn btn-outline-primary" type="submit" data-mdb-ripple-color="dark"> Add Todo </button> </div> </div> </form> </section> {% if todo %} <article class="card container-fluid"> <br/> <h4>Todo ID : {{ todo.id }} </h4> <p> <strong> Item : {{ todo.item }} </strong> </p> </article> {% else %} <section class="container-fluid"> <h2 align="center">Todos</h2> <br> <div class="card"> <ul class="list-group list-group-flush"> {% for todo in todoList %} <li class="list-group-item"> {{ loop.index }}. <a href="/todo/{{ loop.index }}"> {{ todo.item }} </a> </li> {% endfor %} </ul> </div> {% endif %} </section> </main> {% endblock %} |
▶ model.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
from typing import Optional, List from fastapi import Form from pydantic import BaseModel class Todo(BaseModel): id : Optional[int] item : str @classmethod def as_form(cls, item : str = Form(...)): return cls(item = item) class Config: json_schema_extra = { "example" : { "id" : 1, "item": "Example schema!" } } class TodoItem(BaseModel): item : str class Config: json_schema_extra = { "example" : { "item" : "Read the next chapter of the book" } } class TodoItemList(BaseModel): todoList : List[TodoItem] class Config: json_schema_extra = { "example" : { "todoList" : [ { "item" : "Example schema 1!" }, { "item" : "Example schema 2!" } ] } } |
▶ todo_router.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
from fastapi import APIRouter, Path, HTTPException, status, Request, Depends from fastapi.templating import Jinja2Templates from model import Todo, TodoItem, TodoItemList todoList = [] todoAPIRouter = APIRouter() jinja2Templates = Jinja2Templates(directory = "template/") @todoAPIRouter.post("/todo") async def addTodo(request : Request, todo : Todo = Depends(Todo.as_form)): todo.id = len(todoList) + 1 todoList.append(todo) return jinja2Templates.TemplateResponse( "todo.html", { "request" : request, "todoList" : todoList } ) @todoAPIRouter.get("/todo", response_model = TodoItemList) async def getTodo(request : Request): return jinja2Templates.TemplateResponse( "todo.html", { "request" : request, "todoList" : todoList } ) @todoAPIRouter.get("/todo/{todoID}") async def get_single_todo(request : Request, todoID : int = Path(..., title = "The ID of the todo to retrieve.")): for todo in todoList: if todo.id == todoID: return jinja2Templates.TemplateResponse( "todo.html", { "request" : request, "todo" : todo } ) raise HTTPException(status_code = status.HTTP_404_NOT_FOUND, detail = "Todo with supplied ID doesn't exist") @todoAPIRouter.put("/todo/{todoID}") async def update_todo(request : Request, todoItem : TodoItem, todoID : int = Path(..., title="The ID of the todo to be updated.")) -> dict: for todo in todoList: if todo.id == todoID: todo.item = todoItem.item return {"message" : "Todo updated successfully."} raise HTTPException(status_code = status.HTTP_404_NOT_FOUND, detail = "Todo with supplied ID doesn't exist") @todoAPIRouter.delete("/todo/{todoID}") async def delete_single_todo(request : Request, todoID : int) -> dict: for index in range(len(todoList)): todo = todoList[index] if todo.id == todoID: todoList.pop(index) return {"message" : "Todo deleted successfully."} raise HTTPException(status_code = status.HTTP_404_NOT_FOUND, detail = "Todo with supplied ID doesn't exist") @todoAPIRouter.delete("/todo") async def deleteTodoList() -> dict: todoList.clear() return {"message" : "Todos deleted successfully."} |
▶ main.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import uvicorn from fastapi import FastAPI from todo_router import todoAPIRouter fastAPI = FastAPI() @fastAPI.get("/") async def welcome() -> dict: return {"message" : "Hello World"} fastAPI.include_router(todoAPIRouter) if __name__ == "__main__": uvicorn.run("main:fastAPI", host = "0.0.0.0", port = 8000, reload = True) |
▶ requirements.txt
1 2 3 4 5 6 |
fastapi==0.70.0 uvicorn==0.15.0 jinja2 == 3.1.2 python-multipart |