I'm new to using FastAPI, and programming generally. I have been going round in circles trying to remedy this problem. When I attempt to submit the HTML form the only output I'm getting in the console is:
POST http://3.8.197.172:8000/add_car 422 (Unprocessable Entity) add_car @ add_car.html:48 onclick @ add_car.html:40
I think that my Models are set up correctly, but as this is my first time doing this any advice or guidance would be hugely appreciated. I've included my python file and the HTML/JS. Any help would be greatly appreciated.
HTML/JS
<script>
async function add_car()
{
await fetch('http://3.8.197.172:8000/add_car',{
method: "POST",
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
"make": document.add_car_form.make.value,
"model": document.add_car_form.model.value,
"colour": document.add_car_form.colour.value,
"year": document.add_car_form.year.value,
"license_plate": document.add_car_form.license_plate.value,
"seller_name": document.add_car_form.seller_name.value,
"location": document.add_car_form.location.value,
"purchase_price": document.add_car_form.purchase_price.value,
"image_link": document.add_car_form.image_link.value})
})
.then((response) => response.json())
.then((json) => console.log(json));
}
</script>
<form name="add_car_form" method="post">
<label for="make" style="margin: 10px;">Make: </label>
<input type="text" name="make" style="margin: 10px;">
<br>
<label for="model" style="margin: 10px;">Model: </label>
<input type="text" name="model" style="margin: 10px;">
<br>
<label for="colour" style="margin: 10px;">Colour: </label>
<input type="text" name="colour" style="margin: 10px;">
<br>
<label for="year" style="margin: 10px;">Year: </label>
<input type="text" name="year" style="margin: 10px;">
<br>
<label for="license_plate" style="margin: 10px;">Registration: </label>
<input type="text" name="license_plate" style="margin: 10px;">
<br>
<label for="seller_name" style="margin: 10px;">Seller Name: </label>
<input type="text" name="seller_name" style="margin: 10px;">
<br>
<label for="location" style="margin: 10px;">Location: </label>
<input type="text" name="location" style="margin: 10px;">
<br>
<label for="purchase_price" style="margin: 10px;">Purchase Price (£): </label>
<input type="text" name="purchase_price" style="margin: 10px;">
<br>
<label for="image_link" style="margin: 10px;">Image Link: </label>
<input type="text" name="image_link" style="margin: 10px;">
<br>
<p>Click to add car</p>
<input type="button" value="Add Car" style="margin: 10px;" onclick="add_car();">
</form>
main.py
from fastapi import FastAPI, HTTPException, Depends, Body
from sqlalchemy.orm import Session, sessionmaker
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy import Table, Column, Integer, String, Float, MetaData
from pydantic import BaseModel
from sqlalchemy import inspect, create_engine
from sqlalchemy.ext.declarative import declarative_base
import pymysql
host = "localhost"
user = "root"
password = "root123"
database = "CARS_DB"
url = f"mysql+pymysql://{user}:{password}@{host}/{database}"
engine = create_engine(url, echo=True)
if not inspect(engine).has_table("CARS"):
metadata = MetaData()
Cars = Table("CARS", metadata,
Column("id", Integer, primary_key=True,index=True, autoincrement=True),
Column("make", String(80), nullable=False),
Column("model", String(80), nullable=False),
Column("colour", String(80), nullable=False),
Column("year", Integer, nullable=False),
Column("license_plate", String(80), nullable=False),
Column("seller_name", String(80), nullable=False),
Column("location", String(80), nullable=False),
Column("purchase_price", Float(precision=2), nullable=False),
Column("image_link", String(80), nullable=False),
Column("sold_status", String(10), nullable=False, server_default="False"))
metadata.create_all(engine)
connection = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
class Car(BaseModel):
make: str
model: str
colour: str
year: int
license_plate: str
seller_name: str
location: str
purchase_price: float
image_link: str
class Config:
orm_mode = True
class NewCar(Car):
key: str
class Cars(Base):
__tablename__ = "CARS"
id = Column(Integer, primary_key=True,index=True, autoincrement=True)
make = Column(String(80), nullable=False,)
model = Column(String(80), nullable=False,)
colour = Column(String(80), nullable=False,)
year = Column(Integer, nullable=False,)
license_plate = Column(String(80), nullable=False,)
seller_name = Column(String(80), nullable=False,)
location = Column(String(80), nullable=False,)
purchase_price = Column(Float(precision=2), nullable=False,)
image_link = Column(String(80), nullable=False,)
sold_status = Column(String(10), nullable=False, server_default="False")
def get_db():
db = connection()
try:
yield db
finally:
db.close()
# py -m uvicorn main:app --host 0.0.0.0 --reload
#
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
origins = ["*"]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"]
)
@app.get("/")
def root():
return {"message": "Welcome to the Car Dealership backend"}
# show all cars
@app.get("/all_cars")
def get_all_cars(db: Session = Depends(get_db)):
car_list = []
for car in db.query(Cars).all():
car_list.append(car)
return car_list
@app.post("/add_car", response_model=Car)
def add_car(new_car: NewCar, db: Session = Depends(get_db)):
new_car = Car(**new_car.dict())
db.add(new_car)
db.commit()
db.refresh(new_car)
return {"status": "success", "car": new_car}
I've referred to the documentation to no avail.
The result I'm hoping for is to be able to add the form data to my database. I've included my python file and the HTML/JS. Any help would be greatly appreciated.