An Interest In:
Web News this Week
- March 21, 2024
- March 20, 2024
- March 19, 2024
- March 18, 2024
- March 17, 2024
- March 16, 2024
- March 15, 2024
August 16, 2022 05:23 am GMT
Original Link: https://dev.to/soniarpit/todo-app-in-fastapi-with-jinja2-template-5a3
ToDo App in FastAPI with Jinja2 Template
Create Virtual Environment
virtualenv env
and activate it
source env/bin/activate
Installation
pip install fastapi "uvicorn[standard]" jinja2 python-multipart sqlalchemy
Now make main.py, database.py, and model.py in the same directory (in todoapp directory) and also make the templates and static directory, and its look like this,
main.py
# main.pyfrom fastapi import FastAPI, Request, Depends, Form, statusfrom fastapi.templating import Jinja2Templatesimport modelsfrom database import engine, sessionlocalfrom sqlalchemy.orm import Sessionfrom fastapi.responses import RedirectResponsefrom fastapi.staticfiles import StaticFilesmodels.Base.metadata.create_all(bind=engine)templates = Jinja2Templates(directory="templates")app = FastAPI()app.mount("/static", StaticFiles(directory="static"), name="static")def get_db(): db = sessionlocal() try: yield db finally: db.close()@app.get("/")async def home(request: Request, db: Session = Depends(get_db)): todos = db.query(models.Todo).order_by(models.Todo.id.desc()) return templates.TemplateResponse("index.html", {"request": request, "todos": todos})@app.post("/add")async def add(request: Request, task: str = Form(...), db: Session = Depends(get_db)): todo = models.Todo(task=task) db.add(todo) db.commit() return RedirectResponse(url=app.url_path_for("home"), status_code=status.HTTP_303_SEE_OTHER)@app.get("/edit/{todo_id}")async def add(request: Request, todo_id: int, db: Session = Depends(get_db)): todo = db.query(models.Todo).filter(models.Todo.id == todo_id).first() return templates.TemplateResponse("edit.html", {"request": request, "todo": todo})@app.post("/edit/{todo_id}")async def add(request: Request, todo_id: int, task: str = Form(...), completed: bool = Form(False), db: Session = Depends(get_db)): todo = db.query(models.Todo).filter(models.Todo.id == todo_id).first() todo.task = task todo.completed = completed db.commit() return RedirectResponse(url=app.url_path_for("home"), status_code=status.HTTP_303_SEE_OTHER)@app.get("/delete/{todo_id}")async def add(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() return RedirectResponse(url=app.url_path_for("home"), status_code=status.HTTP_303_SEE_OTHER)
database.py
# database.pyfrom sqlalchemy import create_enginefrom sqlalchemy.orm import sessionmakerfrom sqlalchemy.ext.declarative import declarative_baseDB_URL = 'sqlite:///todo.sqlite3'engine = create_engine(DB_URL, connect_args={'check_same_thread': False})sessionlocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)Base = declarative_base()
models.py
# models.pyfrom sqlalchemy import Column, Integer, Boolean, Textfrom database import Baseclass Todo(Base): __tablename__ = 'todos' id = Column(Integer, primary_key=True) task = Column(Text) completed = Column(Boolean, default=False) def __repr__(self): return '<Todo %r>' % (self.id)
Now lets make templates inside the templates directory
templates/base.html
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ToDo App</title> <link rel="stylesheet" href="{{ url_for('static', path='css/main.css') }}"></head><body> <main> <h1>ToDo App</h1> <br> {% block content %} {% endblock content %} </main></body></html>
templates/index.html
{% extends 'base.html' %}{% block content %} <form action="/add" method="post"> <textarea name="task" rows="5" placeholder="Enter your task"></textarea> <button type="submit">Add</button> </form> <br> <h2>Tasks</h2> <div> {% for todo in todos %} <div class="task"> {% if todo.completed %} <strike>{{ todo.task }}</strike> {% else %} {{ todo.task }} {% endif %} <small> <a href="edit/{{ todo.id }}">Edit</a> <a href="delete/{{ todo.id }}">Delete</a> </small> </div> {% endfor %} </div>{% endblock content %}
templates/edit.html
{% extends 'base.html' %}{% block content %} <form action="/edit/{{todo.id}}" method="post"> <textarea name="task" rows="5">{{todo.task}}</textarea> <label for="completed">Done?</label> <input type="checkbox" name="completed" {% if todo.completed %}checked{% endif %}> <button type="submit">Save</button> </form>{% endblock content %}
static/css/main.css
*{ padding: 0; margin: 0; box-sizing: border-box;}body{ font-family: 'Roboto', sans-serif; background: #f5f5f5;}main{ width: 100%; max-width: 520px; margin: 0 auto; padding: 0 20px;}textarea{ width: 100%; height: 100px; border: 1px solid #ccc; border-radius: 5px; padding: 10px; resize: none;}button{ width: 100%; height: 40px; border: 1px solid #ccc; border-radius: 5px; background-color: #eee; color: #333; font-size: 16px; cursor: pointer;}.task{ display: flex; align-items: center; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #ccc;}.task:first-child{ border-top: 1px solid #ccc;}
output
To run the FastAPI app type the following command and hit enter
uvicorn main:app --reload
open link on browser (http://127.0.0.1:8000)
Source code on GitHub: https://github.com/SoniArpit/simple-todoapp-fastapi
Join developer community to share feelings, thoughts, random stuff -> https://awwsome.dev/ (made in django)
Bye <3
Original Link: https://dev.to/soniarpit/todo-app-in-fastapi-with-jinja2-template-5a3
Share this article:
Tweet
View Full Article
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To