首页 > 解决方案 > FastAPI GET 给出 422 Unprocessable Entity 错误

问题描述

我是使用 FastAPI python 的新手,我现在只是想获取数据库中的所有约会。models.py 是使用 sqlacodegen 自动生成的。所以它与数据库是一对一的,我们与数据库有连接。

但问题是,当我尝试访问http://127.0.0.1:8000/appointments时,它会给出以下数据:

{"detail":[{"loc":["query","self"],"msg":"field required","type":"value_error.missing"}]}

并且服务器给出了这个“GET /appointments HTTP/1.1”422 Unprocessable Entity”

但我不知道出了什么问题..

在数据库中,数据如下所示:(虚拟数据) 数据库中的数据

我已经在这里上传了我所有的代码:

模型.py

# coding: utf-8
from sqlalchemy import Column, DateTime, ForeignKey, String, Table
from sqlalchemy.dialects.mysql import INTEGER
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
from .database import Base

Base = declarative_base()
metadata = Base.metadata


class Customer(Base):
    __tablename__ = 'Customer'

    CPR = Column(INTEGER(11), primary_key=True)
    Name = Column(String(45))
    Email = Column(String(45))
    PhoneNumber = Column(INTEGER(11))


class Producer(Base):
    __tablename__ = 'Producer'

    CVR = Column(INTEGER(11), primary_key=True)
    Name = Column(String(45))
    PhoneNumber = Column(INTEGER(11))
    Adress = Column(String(45))

    Supplier = relationship('Supplier', secondary='Producer_has_Supplier')


class Statistic(Base):
    __tablename__ = 'Statistics'

    idStatistics = Column(INTEGER(11), primary_key=True)
    CustomerCount = Column(INTEGER(11))
    ArtistCustomerCount = Column(INTEGER(11))
    SessionCount = Column(INTEGER(11))
    AppliedInkColorCount = Column(INTEGER(11))


class Supplier(Base):
    __tablename__ = 'Supplier'

    CVR = Column(INTEGER(11), primary_key=True)
    Name = Column(String(45))
    PhoneNumber = Column(String(45))
    Adress = Column(String(45))


class Ink(Base):
    __tablename__ = 'Ink'

    BatchNumber = Column(INTEGER(11), primary_key=True, nullable=False)
    Brand = Column(String(45))
    ColorCode = Column(String(15))
    ExperationDate = Column(DateTime)
    Price = Column(INTEGER(11))
    Producer_CVR = Column(ForeignKey('Producer.CVR'), primary_key=True, nullable=False, index=True)

    Producer = relationship('Producer')
    Tattoo = relationship('Tattoo', secondary='Tattoo_has_Ink')


t_Producer_has_Supplier = Table(
    'Producer_has_Supplier', metadata,
    Column('Producer_CVR', ForeignKey('Producer.CVR'), primary_key=True, nullable=False, index=True),
    Column('Supplier_CVR', ForeignKey('Supplier.CVR'), primary_key=True, nullable=False, index=True)
)


class Tattooparlor(Base):
    __tablename__ = 'Tattooparlor'

    CVR = Column(INTEGER(11), primary_key=True, nullable=False)
    Name = Column(String(75))
    Adress = Column(String(45))
    PhoneNumber = Column(INTEGER(11))
    Email = Column(String(45))
    Statistics_idStatistics = Column(ForeignKey('Statistics.idStatistics'), primary_key=True, nullable=False, index=True)
    Supplier_CVR = Column(ForeignKey('Supplier.CVR'), primary_key=True, nullable=False, index=True)

    Statistic = relationship('Statistic')
    Supplier = relationship('Supplier')


class Artist(Base):
    __tablename__ = 'Artist'

    CPR = Column(INTEGER(11), primary_key=True)
    Name = Column(String(45))
    PhoneNumber = Column(INTEGER(11))
    Email = Column(String(45))
    Price = Column(INTEGER(11))
    Tattooparlor_CVR = Column(ForeignKey('Tattooparlor.CVR'), nullable=False, index=True)

    Tattooparlor = relationship('Tattooparlor')


t_Parlor_has_Ink = Table(
    'Parlor_has_Ink', metadata,
    Column('Ink_batchnumber', ForeignKey('Ink.BatchNumber'), index=True),
    Column('Parlor_storageID', ForeignKey('Tattooparlor.CVR'), index=True),
    Column('Quantity', INTEGER(11))
)


class Appointment(Base):
    __tablename__ = 'Appointment'

    id = Column(INTEGER(11), primary_key=True, nullable=False)
    DateTime = Column(DateTime)
    SessionLenght = Column(INTEGER(11))
    Customer_CPR = Column(ForeignKey('Customer.CPR'), primary_key=True, nullable=False, index=True)
    Tattooparlor_CVR = Column(ForeignKey('Tattooparlor.CVR'), primary_key=True, nullable=False, index=True)
    Artist_CPR = Column(ForeignKey('Artist.CPR'), nullable=False, index=True)

    Artist = relationship('Artist')
    Customer = relationship('Customer')
    Tattooparlor = relationship('Tattooparlor')


class Tattoo(Base):
    __tablename__ = 'Tattoo'

    idTattoo = Column(INTEGER(11), primary_key=True, nullable=False)
    Description = Column(String(200))
    PlacementOnBody = Column(String(45))
    Appointment_idAppointment = Column(ForeignKey('Appointment.idAppointment'), primary_key=True, nullable=False, index=True)

    Appointment = relationship('Appointment')


t_Tattoo_has_Ink = Table(
    'Tattoo_has_Ink', metadata,
    Column('Tattoo_idTattoo', ForeignKey('Tattoo.idTattoo'), primary_key=True,   nullable=False, index=True),
    Column('Ink_BatchNumber', ForeignKey('Ink.BatchNumber'), primary_key=True, nullable=False, index=True)
)

模式.py

from typing import List
from sqlalchemy.orm import Session
from .models import Appointment
from .schemas import AppointmentBase

# Function to get list of car info
def get_all_apointments(session: Session) -> List[Appointment]:
    print(List[Appointment])
    return session.query(Appointment).all()

crud.py

from typing import List, Optional
from pydantic import BaseModel
import datetime

# TO support creation and update APIs
class AppointmentBase(BaseModel):
    DateTime = str(datetime)
    SessionLenght = int


# TO support list and get APIs
class Appointment(AppointmentBase):
    Appointment_id = int
    Customer_CPR = int
    Tattooparlor_CVR =int
    Artist_CPR = int

    class Config:
        orm_mode = True
        arbitrary_types_allowed = True

# To support list API
class PaginatedAppointmentInfo(BaseModel):
    data: List[Appointment] = []

    class Config:
        orm_mode = True
        arbitrary_types_allowed = True

主文件

from fastapi import Depends, FastAPI, HTTPException
from sqlalchemy.orm import Session
from pydantic import BaseModel
import uvicorn
from . import models
from .database import SessionLocal, engine
from .schemas import Appointment, AppointmentBase, PaginatedAppointmentInfo
from .crud import get_all_apointments

# Initialize the app
app = FastAPI()

models.Base.metadata.create_all(bind=engine)

app = FastAPI()

# Dependency
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

# API to get the list of car info
@app.get("/appointments", response_model=PaginatedAppointmentInfo)
def list_apointments(self):
        apointments_list = get_all_apointments(self.session)
        response = {"data": apointments_list}
        return response

# GET operation at route '/'
@app.get('/')
def root_api():
    return {"message": "Welcome to Balasundar's Technical Blog"}

标签: pythonsqlalchemyfastapi

解决方案


错误消息告诉您,您已经定义了一个未提交的名为的必需查询参数:self

{"detail":[{"loc":["query","self"],"msg":"field required"
                    ^       ^
                    type    name

如果您查看您正在调用的函数,您会看到您有一个提到该特定名称的定义:

# API to get the list of car info
@app.get("/appointments", response_model=PaginatedAppointmentInfo)
def list_apointments(self):
                     ^
                     

由于常规函数没有隐式的第一个参数(仅适用于类中的方法),FastAPI 期望为self函数提供一个参数。既然你没有包括它——我猜你已经从一个类中提取了这个,因为你也在使用self.session更远的地方——FastAPI 给出了一个错误。

由于您已经定义了get_db获取会话的依赖项,因此您可能应该使用它(因为self在类上下文之外没有任何特殊含义):

# API to get the list of car info
@app.get("/appointments", response_model=PaginatedAppointmentInfo)
def list_apointments(session = Depends(get_db)):
        apointments_list = get_all_apointments(session)
        response = {"data": apointments_list}
        return response

该函数不再有任何必需的参数 - 从中​​检索会话get_db并且该函数没有其他参数。


推荐阅读