В чем смысл моделей (схем) pydanti c в Python при создании API с FastAPI - PullRequest
1 голос
/ 15 февраля 2020

Я новичок в python, и я пытаюсь построить API с FastAPI.
Пока это работает, я подключился к postgres db, я сделал post / get / request и все работает, но у меня нет хорошего понимания, почему мы определяем схемы, как это, почему мы должны создавать

класс UserBase (BaseModel)
класс UserCreate (UserBase)
класс User (UserBase)

Я опубликую исходный код для всех файлов, и если вы, ребята, поможете мне лучше понять это, это действительно очень мне поможет, потому что я ' у нас есть задание на завтра.


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 должен быть для проверки с помощью pydanti c, но как насчет двух других, кто-то может дать мне хорошее объяснение ..

* 10 30 * Спасибо.

1 Ответ

1 голос
/ 15 февраля 2020
Схемы

Pydanti c определяют свойства и типы для проверки некоторой полезной нагрузки.

Они действуют как охранник, прежде чем вы фактически разрешаете службе выполнять определенное действие (например, создавать объект базы данных). Я не уверен, что вы привыкли к сериализаторам, но это почти то же самое, за исключением того, что Pydanti c и FastAPI интегрируются со свойствами newi sh Python 3 (см. проверка типов ), которые несколько упрощает достижение того, что вы делали со встроенными библиотеками / библиотеками.

В вашем примере UserCreate требует только пароль и адрес электронной почты, поэтому наследование делает ваш код более DRY .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...