Исправление документации swagger и ошибок обновления данных

This commit is contained in:
2026-02-25 00:12:09 +03:00
parent e8e3310afa
commit 8e10af0bfd
11 changed files with 39 additions and 16 deletions
+1
View File
@@ -45,6 +45,7 @@ coverage.xml
*.py,cover
.hypothesis/
.pytest_cache/
.ruff_cache/
# pyenv
.python-version
+1 -1
View File
@@ -25,7 +25,7 @@ class AuthorCreate(AuthorBase):
class AuthorUpdate(SQLModel):
"""Модель автора для обновления"""
name: str | None = Field(None, description="Псевдоним")
name: str | None = Field(None, description="Псевдоним", schema_extra={"examples": [None]})
class AuthorRead(AuthorBase):
+4 -4
View File
@@ -35,10 +35,10 @@ class BookCreate(BookBase):
class BookUpdate(SQLModel):
"""Модель книги для обновления"""
title: str | None = Field(None, description="Название")
description: str | None = Field(None, description="Описание")
page_count: int | None = Field(None, description="Количество страниц")
status: BookStatus | None = Field(None, description="Статус")
title: str | None = Field(None, description="Название", schema_extra={"examples": [None]})
description: str | None = Field(None, description="Описание", schema_extra={"examples": [None]})
page_count: int | None = Field(None, description="Количество страниц", schema_extra={"examples": [None]})
status: BookStatus | None = Field(None, description="Статус", schema_extra={"examples": [None]})
class BookRead(BookBase):
+1 -1
View File
@@ -25,7 +25,7 @@ class GenreCreate(GenreBase):
class GenreUpdate(SQLModel):
"""Модель жанра для обновления"""
name: str | None = Field(None, description="Название")
name: str | None = Field(None, description="Название", schema_extra={"examples": [None]})
class GenreRead(GenreBase):
+1 -1
View File
@@ -104,7 +104,7 @@ class UserUpdateByAdmin(UserUpdate):
"""Обновление пользователя администратором"""
is_active: bool = Field(True, description="Не является ли заблокированным")
roles: list[str] | None = Field(None, description="Роли")
roles: list[str] | None = Field(None, description="Роли", schema_extra={"examples": [None]})
class LoginResponse(SQLModel):
+3 -3
View File
@@ -71,9 +71,9 @@ class UserRead(UserBase):
class UserUpdate(SQLModel):
"""Модель пользователя для обновления"""
email: EmailStr | None = Field(None, description="Email")
full_name: str | None = Field(None, description="Полное имя")
password: str | None = Field(None, description="Пароль")
email: EmailStr | None = Field(None, description="Email", schema_extra={"examples": [None]})
full_name: str | None = Field(None, description="Полное имя", schema_extra={"examples": [None]})
password: str | None = Field(None, description="Пароль", schema_extra={"examples": [None]})
class UserList(SQLModel):
+2
View File
@@ -105,6 +105,8 @@ def update_author(
update_data = author.model_dump(exclude_unset=True)
for field, value in update_data.items():
if value is None:
continue
setattr(db_author, field, value)
session.commit()
+19 -3
View File
@@ -62,7 +62,12 @@ from sqlalchemy import select, func, distinct, case, exists
from sqlalchemy.orm import selectinload
@router.get("/filter", response_model=BookFilteredList)
@router.get(
"/filter",
response_model=BookFilteredList,
summary="Поиск по книгам",
description="Фильтрует и ищет книги",
)
def filter_books(
current_user: OptionalAuth,
session: Session = Depends(get_session),
@@ -74,6 +79,7 @@ def filter_books(
page: int = Query(1, gt=0),
size: int = Query(20, gt=0, le=100),
):
"""Выполняет поиск книги в системе"""
statement = select(Book).options(
selectinload(Book.authors), selectinload(Book.genres), defer(Book.embedding) # ty: ignore
)
@@ -315,13 +321,18 @@ def delete_book(
session.commit()
return book_read
@router.post("/{book_id}/preview")
@router.post(
"/{book_id}/preview",
summary="Утановить обложку книги",
description="Меняет обложку книги в системе",
)
async def upload_book_preview(
current_user: RequireStaff,
file: UploadFile = File(...),
book_id: int = Path(..., gt=0),
session: Session = Depends(get_session)
):
"""Загружает обложку книги в систему"""
if not (file.content_type or "").startswith("image/"):
raise HTTPException(
status_code=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE,
@@ -369,12 +380,17 @@ async def upload_book_preview(
}
@router.delete("/{book_id}/preview")
@router.delete(
"/{book_id}/preview",
summary="Удалить обложку книги",
description="Удаляет обложку книги в системе",
)
async def remove_book_preview(
current_user: RequireStaff,
book_id: int = Path(..., gt=0),
session: Session = Depends(get_session)
):
"""Убирает обложку книги в системе"""
book = session.get(Book, book_id)
if not book:
raise HTTPException(status.HTTP_404_NOT_FOUND, "Book not found")
+2
View File
@@ -104,6 +104,8 @@ def update_genre(
update_data = genre.model_dump(exclude_unset=True)
for field, value in update_data.items():
if value is None:
continue
setattr(db_genre, field, value)
session.commit()
+4 -2
View File
@@ -1,7 +1,9 @@
[project]
name = "LiB"
version = "0.9.0"
description = "Это простое API для управления авторами, книгами и их жанрами."
version = "0.9.1"
description = """REST API библиотечной системы. Позволяет вести каталог книг с авторами и жанрами, отслеживать выдачи и возвраты книг читателями.
С ролевой моделью: читатель, библиотекарь, администратор. Для авторизованных пользователей доступен векторный поиск книг по названию и описанию.
Для безопасности используется шифрование, CAPTCH, 2FA и одноразовые коды коды восстановления пароля."""
authors = [{ name = "wowlikon" }]
readme = "README.md"
requires-python = ">=3.12"
Generated
+1 -1
View File
@@ -627,7 +627,7 @@ sdist = { url = "https://files.pythonhosted.org/packages/e8/ef/324f4a28ed0152a32
[[package]]
name = "lib"
version = "0.9.0"
version = "0.9.1"
source = { editable = "." }
dependencies = [
{ name = "aiofiles" },