article

Friday, January 20, 2023

Python FastAPI To Do with Jinja2 Template

Python FastAPI To Do with Jinja2 Template

Install Fastapi

https://github.com/tiangolo/fastapi

pip install fastapi
C:\fastAPI\myapp>pip install fastapi
C:\fastAPI\myapp>pip install "uvicorn[standard]"

Install sqlalchemy jinja2
pip install python-multipart sqlalchemy jinja2
C:\fastAPI\myapp>pip install python-multipart sqlalchemy jinja2

Create app.py
myapp/app.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
//myapp/app.py
from fastapi import FastAPI, Depends, Request, Form, status
 
from starlette.responses import RedirectResponse
from starlette.templating import Jinja2Templates
 
from sqlalchemy.orm import Session
 
import models
from database import SessionLocal, engine
 
models.Base.metadata.create_all(bind=engine)
 
templates = Jinja2Templates(directory="templates")
 
app = FastAPI()
 
 
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()
 
 
@app.get("/")
def home(request: Request, db: Session = Depends(get_db)):
    todos = db.query(models.Todo).all()
    return templates.TemplateResponse("index.html",
                                      {"request": request, "todo_list": todos})
 
@app.post("/add")
def add(request: Request, title: str = Form(...), db: Session = Depends(get_db)):
    new_todo = models.Todo(title=title)
    db.add(new_todo)
    db.commit()
 
    url = app.url_path_for("home")
    return RedirectResponse(url=url, status_code=status.HTTP_303_SEE_OTHER)
 
 
@app.get("/update/{todo_id}")
def update(request: Request, todo_id: int, db: Session = Depends(get_db)):
    todo = db.query(models.Todo).filter(models.Todo.id == todo_id).first()
    todo.complete = not todo.complete
    db.commit()
 
    url = app.url_path_for("home")
    return RedirectResponse(url=url, status_code=status.HTTP_302_FOUND)
 
 
@app.get("/delete/{todo_id}")
def delete(request: Request, todo_id: int, db: Session = Depends(get_db)):
    todo = db.query(models.Todo).filter(models.Todo.id == todo_id).first()
    db.delete(todo)
    db.commit()
 
    url = app.url_path_for("home")
    return RedirectResponse(url=url, status_code=status.HTTP_302_FOUND)
myapp/database.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//myapp/database.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
 
SQLALCHEMY_DATABASE_URL = "sqlite:///./db.sqlite"
# SQLALCHEMY_DATABASE_URL = "postgresql://user:password@postgresserver/db"
 
engine = create_engine(
    SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
 
Base = declarative_base()
myapp/models.py
1
2
3
4
5
6
7
8
9
10
11
//myapp/models.py
from sqlalchemy import Boolean, Column, Integer, String
 
from database import Base
 
class Todo(Base):
    __tablename__ = "todos"
 
    id = Column(Integer, primary_key=True, index=True)
    title = Column(String)
    complete = Column(Boolean, default=False)
make templates inside the templates directory
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
//myapp/templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Python FastAPI To Do with Jinja2 Template</title>
</head>
<body>
<section class="vh-100" style="background-color: #eee;">
  <div class="container py-5 h-100">
    <div class="row d-flex justify-content-center align-items-center h-100">
      <div class="col col-lg-9 col-xl-7">
        <div class="card rounded-3">
          <div class="card-body p-4">
 
            <h4 class="text-center my-3 pb-3">Python FastAPI To Do with Jinja2 Template</h4>
            <form class="row" action="/add" method="post">
              <div class="col-4">
                <div class="form-outline">
                  <input type="text" id="title" name="title" class="form-control" placeholder="Enter a task here"/>
                </div>
              </div>
 
              <div class="col-6">
                <button type="submit" class="btn btn-primary">Save</button>
              </div>
            </form>
 
            <table class="table mb-4">
                <thead>
                    <tr>
                      <th scope="col">No.</th>
                      <th scope="col">Todo item</th>
                      <th scope="col">Status</th>
                      <th scope="col">Actions</th>
                    </tr>
                </thead>
                <tbody>
                    {% for todo in todo_list %}
                    <tr>
                      <th scope="row">{{todo.id }}</th>
                      <td>{{ todo.title }}</td>
                      <td>
                        {% if todo.complete == False %}
                        <div class="alert alert-secondary" role="alert">In progress</div>
                        {% else %}
                        <div class="alert alert-success" role="alert">Completed</div>
                        {% endif %}
                      </td>
                      <td>
                        <a class="btn btn-success" href="/update/{{ todo.id }}">Update</a>
                        <a class="btn btn-danger ms-1" href="/delete/{{ todo.id }}">Delete</a>
                      </td>
                    </tr>
                    {% endfor %}
                </tbody>
            </table>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>
</body>
</html>  
run the FastAPI app

C:\fastAPI\myapp>uvicorn app:app --reload

with uvicorn using the file_name:app_instance
open the link on the browser http://127.0.0.1:8000/
http://127.0.0.1:8000/docs

Related Post