Archived
- Backend: Book model with reading progress, DRF ViewSet with full CRUD, search, sort, filter, pagination, mark-as-finished, stats endpoint - Frontend: Library grid, BookCard, BookDetail, BookForm components with React 19 + TypeScript + Vite - Tests: 29 passing tests covering models, API, serializers, permissions - Spec: backend api-spec.md and frontend component-spec.md in docs/ Closes crisleo-hermes/cloud-reader#3
84 lines
3.8 KiB
Markdown
84 lines
3.8 KiB
Markdown
# Backend API Specification — Cloud Reader
|
|
|
|
## Overview
|
|
|
|
The Cloud Reader backend provides a RESTful API for managing a user's personal book library. Built with Django 5 + Django REST Framework.
|
|
|
|
## Models
|
|
|
|
### Book
|
|
|
|
| Field | Type | Constraints |
|
|
|------------------|--------------------|---------------------------------|
|
|
| `title` | `CharField(500)` | Required |
|
|
| `author` | `CharField(500)` | Required |
|
|
| `genre` | `CharField(200)` | Optional, blank allowed |
|
|
| `description` | `TextField` | Optional, blank allowed |
|
|
| `cover_image_url`| `URLField` | Optional, blank allowed |
|
|
| `isbn` | `CharField(20)` | Optional, blank allowed |
|
|
| `total_pages` | `PositiveIntegerField` | Default 0 |
|
|
| `current_page` | `PositiveIntegerField` | Default 0, validated ≤ total |
|
|
| `reading_status` | `CharField(20)` | Choices: `not_started`, `reading`, `finished`, `dnf` |
|
|
| `owner` | `ForeignKey(User)` | Set automatically on create |
|
|
| `created_at` | `DateTimeField` | Auto-set on create |
|
|
| `updated_at` | `DateTimeField` | Auto-set on update |
|
|
|
|
**Properties:**
|
|
- `reading_progress` — computed `(current_page / total_pages) * 100`, returns `0.0` when `total_pages` is 0.
|
|
|
|
**Indexes:** Composite indexes on `(owner, reading_status)`, `(owner, title)`, `(owner, author)`.
|
|
|
|
## API Endpoints
|
|
|
|
Base URL: `/api/`
|
|
|
|
Authentication: SessionAuthentication + BasicAuthentication (DRF defaults).
|
|
|
|
Permissions: All book endpoints require `IsAuthenticated`. Users can only access their own books.
|
|
|
|
### Books
|
|
|
|
| Method | URL | Action | Serializer |
|
|
|----------|------------------------------------|---------------|--------------------|
|
|
| `GET` | `/api/books/` | List books | `BookListSerializer` |
|
|
| `POST` | `/api/books/` | Create book | `BookDetailSerializer` |
|
|
| `GET` | `/api/books/{id}/` | Retrieve book | `BookDetailSerializer` |
|
|
| `PUT` | `/api/books/{id}/` | Full update | `BookDetailSerializer` |
|
|
| `PATCH` | `/api/books/{id}/` | Partial update| `BookDetailSerializer` |
|
|
| `DELETE` | `/api/books/{id}/` | Delete book | — |
|
|
| `POST` | `/api/books/{id}/mark_finished/` | Mark finished | `BookDetailSerializer` |
|
|
| `GET` | `/api/books/stats/` | Library stats | — (custom) |
|
|
|
|
### Query Parameters (List)
|
|
|
|
| Parameter | Type | Description |
|
|
|------------------|----------|--------------------------------------------------|
|
|
| `page` | int | Page number for pagination (20 items/page) |
|
|
| `sort_by` | string | `title`, `-title`, `author`, `-author`, `-created_at`, `-updated_at`, `-reading_progress`, `reading_progress` |
|
|
| `reading_status` | string | Filter by status value |
|
|
| `search` | string | Search in title and author fields (icontains) |
|
|
|
|
### Stats Response
|
|
|
|
```json
|
|
{
|
|
"total_books": 10,
|
|
"finished": 3,
|
|
"reading": 4,
|
|
"not_started": 3
|
|
}
|
|
```
|
|
|
|
### Mark Finished
|
|
|
|
`POST /api/books/{id}/mark_finished/` sets `reading_status` to `finished` and `current_page` to `total_pages`.
|
|
|
|
## Validation Rules
|
|
|
|
- Title and author cannot be empty or whitespace-only
|
|
- `current_page` cannot exceed `total_pages` (when `total_pages > 0`)
|
|
- Setting `reading_status` to `finished` automatically sets `current_page = total_pages`
|
|
|
|
## Admin
|
|
|
|
Books are registered in Django admin with list display, filters by `reading_status` and `genre`, and search by `title`/`author`. |