在使用 FastAPI 构建 API 时,Python 中的 pydantic 模型(模式)是什么意思

What is the meaning of pydantic models(schemas) in Python while building an API with FastAPI

我是 python 的新人,我正在尝试使用 FastAPI 构建一个 API。
它目前正在运行,我连接了 postgres db,我发出了 post/get/ 请求,一切正常,但我不太理解为什么我们要这样定义模式,为什么我们必须创建一个

class 用户基础(基础模型)
class 用户创建(用户基础)
class 用户(用户群)

我将 post 所有文件的源代码,如果你们能帮助我更好地理解这一点,那将对我有很大帮助,因为我有一个明天的作业。


schemas.py

from typing import List
from pydantic import BaseModel

##BOOKING
class BookingBase(BaseModel):
    name:str
    description:str = None

class BookingCreate(BookingBase):
    pass

class Booking(BookingBase):
    id:int
    user_id:int

    class Config:
        orm_mode = True

##USER
class UserBase(BaseModel):
    email: str

class UserCreate(UserBase):
    password: str

class User(UserBase):
    id: int
    is_active: bool
    bookings: List[Booking] = []

    class Config:
        orm_mode = True

models.py

from .database import Base
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String,DateTime
from sqlalchemy.sql import func
from sqlalchemy.orm import relationship

class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True,index=True)
    email = Column(String, unique=True, index= True)
    hashed_password = Column(String)
    is_active = Column(Boolean,default=True)

    bookings = relationship("Booking", back_populates="owner")

class Booking(Base):
    __tablename__ = "bookings"

    id=Column(Integer,primary_key=True,index=True)
    name = Column(String,index=True)
    description = Column(String, index=True)
    created_date = Column(DateTime, server_default=func.now())
    user_id = Column(Integer,ForeignKey("users.id"))

    owner = relationship("User",back_populates="bookings")

crud.py

from . import models,schemas
from sqlalchemy.orm import Session

def get_user(db:Session,user_id:int):
    return db.query(models.User).filter(models.User.id == user_id).first()

def fetch_user_by_email(db:Session,email:str):
    return db.query(models.User).filter(models.User.email == email).first()

def get_all_users(db: Session, skip: int = 0, limit: int = 100):
    return db.query(models.User).offset(skip).limit(limit).all()


def get_bookings(db:Session,skip:int=0,limit:int=100):
    return db.query(models.Booking).offset(skip).limit(limit).all()

def create_new_user(db:Session,user:schemas.UserCreate):
    testing_hashed = user.password + "test"
    db_user = models.User(email=user.email,hashed_password=testing_hashed)
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    return db_user


def create_user_booking(db: Session, booking: schemas.BookingCreate, user_id: int):
    db_item = models.Booking(**booking.dict(), user_id=user_id)
    db.add(db_item)
    db.commit()
    db.refresh(db_item)
    return db_item

database.py

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker


# SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
SQLALCHEMY_DATABASE_URL = "postgresql://postgres:root@localhost/meetingbookerdb"

##Creating the SQLAlchemy ORM engine..>> above we have imported create_engine method from sqlalchemy
##Since we are using Postgres we dont need anything else

create_engine

engine = create_engine(
    SQLALCHEMY_DATABASE_URL
)

#Creating SessionLocal class which will be database session on the request..

SessionLocal = sessionmaker(autocommit=False,autoflush=False,bind=engine)

## Creating the base clase, using the declerative_base() method which returns a class.
## Later we will need this Base Class to create each of the database models

Base = declarative_base()

和main.py

from typing import List

from fastapi import Depends, FastAPI, HTTPException
from sqlalchemy.orm import Session

from .app import crud, models, schemas
from .app.database  import SessionLocal, engine

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


app = FastAPI()


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


@app.post("/users/", response_model=schemas.User)
def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)):
    db_user = crud.fetch_user_by_email(db, email=user.email)
    if db_user:
        raise HTTPException(status_code=400, detail="Email already registered")
    return crud.create_new_user(db=db, user=user)


@app.get("/users/", response_model=List[schemas.User])
def read_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
    users = crud.get_all_users(db, skip=skip, limit=limit)
    return users


@app.get("/users/{user_id}", response_model=schemas.User)
def read_user(user_id: int, db: Session = Depends(get_db)):
    db_user = crud.get_user(db, user_id=user_id)
    if db_user is None:
        raise HTTPException(status_code=404, detail="User not found")
    return db_user


@app.post("/users/{user_id}/bookings/", response_model=schemas.Booking)
def create_booking_for_user(
    user_id: int,booking: schemas.BookingCreate, db: Session = Depends(get_db)
):
    return crud.create_user_booking(db=db, booking=booking, user_id=user_id)


@app.get("/bookings/", response_model=List[schemas.Booking])
def read_bookings(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
    bookings = crud.get_bookings(db, skip=skip, limit=limit)
    return bookings

问题是,为什么我们必须像那样创建这些模式,好的,我明白了第一个 UserBase 必须用于使用 pydantic 进行验证,但是其他两个呢,有人可以给我一个很好的解释..

谢谢。

Pydantic 模式定义了属性和类型来验证一些有效负载。

在您实际允许服务完成特定操作(例如创建数据库对象)之前,它们就像守卫一样。我不确定你是否习惯了序列化程序,但除了 Pydantic 和 FastAPI 与新的 Python 3 个属性(参见 type checking)集成之外,它几乎是一样的,这使得实现你以前用框架做的事情 builtins/libraries.

在您的示例中,UserCreate 仅需要密码和电子邮件地址,因此继承使您的代码更加 DRY