Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions crud.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from sqlalchemy.orm import Session

import models
import schemas


def get_author(db: Session, author_id: int):
return db.query(models.Author).filter(models.Author.id == author_id).first()


def get_author_by_name(db: Session, name: str):
return db.query(models.Author).filter(models.Author.name == name).first()


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


def create_author(db: Session, author: schemas.AuthorCreate):
db_author = models.Author(name=author.name, bio=author.bio)
db.add(db_author)
db.commit()
db.refresh(db_author)
return db_author


def get_book(db: Session, book_id: int):
return db.query(models.Book).filter(models.Book.id == book_id).first()


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


def get_books_by_author(db: Session, author_id: int, skip: int = 0, limit: int = 100):
return (
db.query(models.Book)
.filter(models.Book.author_id == author_id)
.offset(skip)
.limit(limit)
.all()
)


def create_book(db: Session, book: schemas.BookCreate, author_id: int):
db_book = models.Book(
title=book.title,
summary=book.summary,
publication_date=book.publication_date,
author_id=author_id,
)
db.add(db_book)
db.commit()
db.refresh(db_book)
return db_book
13 changes: 13 additions & 0 deletions database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

SQLALCHEMY_DATABASE_URL = "sqlite:///./library.db"

engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)

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

Base = declarative_base()
64 changes: 64 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from fastapi import Depends, FastAPI, HTTPException, Query
from sqlalchemy.orm import Session

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

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

app = FastAPI(title="Library Management API")


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


@app.post("/authors/", response_model=schemas.AuthorRead, status_code=201)
def create_author(author: schemas.AuthorCreate, db: Session = Depends(get_db)):
existing = crud.get_author_by_name(db, name=author.name)
if existing:
raise HTTPException(status_code=400, detail="Author with this name already exists")
return crud.create_author(db=db, author=author)


@app.get("/authors/", response_model=list[schemas.AuthorRead])
def read_authors(
skip: int = Query(0, ge=0), limit: int = Query(100, ge=1), db: Session = Depends(get_db)
):
return crud.get_authors(db, skip=skip, limit=limit)


@app.get("/authors/{author_id}", response_model=schemas.AuthorRead)
def read_author(author_id: int, db: Session = Depends(get_db)):
db_author = crud.get_author(db, author_id=author_id)
if db_author is None:
raise HTTPException(status_code=404, detail="Author not found")
return db_author


@app.post("/authors/{author_id}/books/", response_model=schemas.BookRead, status_code=201)
def create_book_for_author(
author_id: int, book: schemas.BookCreate, db: Session = Depends(get_db)
):
db_author = crud.get_author(db, author_id=author_id)
if db_author is None:
raise HTTPException(status_code=404, detail="Author not found")
return crud.create_book(db=db, book=book, author_id=author_id)


@app.get("/books/", response_model=list[schemas.BookRead])
def read_books(
author_id: int | None = Query(None, alias="authorId"),
skip: int = Query(0, ge=0),
limit: int = Query(100, ge=1),
db: Session = Depends(get_db),
):
if author_id is not None:
return crud.get_books_by_author(db, author_id=author_id, skip=skip, limit=limit)
return crud.get_books(db, skip=skip, limit=limit)
26 changes: 26 additions & 0 deletions models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from sqlalchemy import Column, Date, ForeignKey, Integer, String
from sqlalchemy.orm import relationship

from database import Base


class Author(Base):
__tablename__ = "authors"

id = Column(Integer, primary_key=True, index=True)
name = Column(String, unique=True, nullable=False, index=True)
bio = Column(String, nullable=True)

books = relationship("Book", back_populates="author", cascade="all, delete-orphan")


class Book(Base):
__tablename__ = "books"

id = Column(Integer, primary_key=True, index=True)
title = Column(String, nullable=False, index=True)
summary = Column(String, nullable=True)
publication_date = Column(Date, nullable=False)
author_id = Column(Integer, ForeignKey("authors.id"), nullable=False)

author = relationship("Author", back_populates="books")
39 changes: 39 additions & 0 deletions schemas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from datetime import date
from typing import List, Optional

from pydantic import BaseModel


class BookBase(BaseModel):
title: str
summary: Optional[str] = None
publication_date: date


class BookCreate(BookBase):
pass


class BookRead(BookBase):
id: int
author_id: int

class Config:
orm_mode = True


class AuthorBase(BaseModel):
name: str
bio: Optional[str] = None


class AuthorCreate(AuthorBase):
pass


class AuthorRead(AuthorBase):
id: int
books: List[BookRead] = []

class Config:
orm_mode = True