Install Fastapi
https://github.com/tiangolo/fastapi
pip install fastapi
C:\fastAPI\registration>pip install fastapi
C:\fastAPI\registration>pip install "uvicorn[standard]"
Install sqlalchemy jinja2
pip install python-multipart sqlalchemy jinja2
C:\fastAPI\registration>pip install python-multipart sqlalchemy jinja2
Create main.py
registration/main.py
registration/main.py
#registration/main.py
from fastapi import FastAPI, Request, Depends, Form, status
from fastapi.templating import Jinja2Templates
import models
from database import engine, sessionlocal
from sqlalchemy.orm import Session
from fastapi import responses
from sqlalchemy.exc import IntegrityError
from fastapi.responses import RedirectResponse
from forms import UserCreateForm
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("/")
async def home(request: Request, db: Session = Depends(get_db)):
return templates.TemplateResponse("index.html", {"request": request})
@app.post("/register/")
async def register(request: Request, username: str = Form(...), email: str = Form(...), password: str = Form(...), db: Session = Depends(get_db)):
form = UserCreateForm(request)
await form.load_data()
print("submited")
if await form.is_valid():
try:
print(username)
print(email)
print(password)
total_row = db.query(models.User).filter(models.User.email == email).first()
print(total_row)
if total_row == None:
print("Save")
users = models.User(username=username, email=email, password=password)
db.add(users)
db.commit()
return responses.RedirectResponse(
"/", status_code=status.HTTP_302_FOUND
)
else:
print("taken email")
errors = ["The email has already been taken"]
except IntegrityError:
return {"msg":"Error"}
else:
print("Error Form")
errors = form.errors
return templates.TemplateResponse("index.html", {"request": request, "errors": errors})
registration/database.py
#registration/database.py
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
DB_URL = 'sqlite:///fastapidb.sqlite3'
engine = create_engine(DB_URL, connect_args={'check_same_thread': False})
sessionlocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
registration/models.py
#registration/models.py
from sqlalchemy import Column, Integer, String
from database import Base
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String(150))
email = Column(String(150))
password = Column(String(150))
def __repr__(self):
return '<User %r>' % (self.id)
registration/forms.py
#registration/forms.py
from typing import List
from typing import Optional
from fastapi import Request
class UserCreateForm:
def __init__(self, request: Request):
self.request: Request = request
self.errors: List = []
self.username: Optional[str] = None
self.email: Optional[str] = None
self.password: Optional[str] = None
async def load_data(self):
form = await self.request.form()
self.username = form.get("username")
self.email = form.get("email")
self.password = form.get("password")
async def is_valid(self):
if not self.username or not len(self.username) > 3:
self.errors.append("Username should be > 3 chars")
if not self.email or not (self.email.__contains__("@")):
self.errors.append("Email is required")
if not self.password or not len(self.password) >= 4:
self.errors.append("Password must be > 4 chars")
if not self.errors:
return True
return False
make templates inside the templates directory registration/templates/base.html
//registration/templates/index.html
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row">
<div class="text-danger font-weight-bold">
<ul>
{% for error in errors %}
<li class="alert alert-danger">{{error}}</li>
{% endfor %}
</ul>
</div>
</div>
<div class="row my-5">
<form action = "/register" method = "post">
<div class="mb-3">
<label>Username</label>
<input type="text" required class="form-control" name="username" value="" placeholder="username">
</div>
<div class="mb-3">
<label>Email</label>
<input type="text" required placeholder="Your email" name="email" value="" class="form-control">
</div>
<div class="mb-3">
<label>Password</label>
<input type="password" required placeholder="Choose a secure password" value="" name="password" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
<style>
ul {
list-style-type: none;
}
</style>
{% endblock content %}
registration/temmplates/base.html
//registration/temmplates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FastAPI Registration Form with sqlalchemy Jinja2 Template - Cairocoders</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h1 class="page-header text-center">FastAPI Registration Form Validation with sqlalchemy Jinja2 Template</h1>
{% block content %}
{% endblock content %}
</div>
</body>
</html>
run the FastAPI app C:\fastAPI\registration>uvicorn main: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
