0

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.

flvy
  • 1
  • 1
  • 1
    According to your `NewCar` model there is also a required parameter that is named `key`, but there doesn't seem to be any JSON key matching that name in your request. Also, if you look at the response from FastAPI the body of the 422 response will tell you exactly which fields are missing or what failed validation. – MatsLindh Jun 26 '23 at 12:04

0 Answers0