Archived
feat: bookmarks and notes management
- Backend: Django REST Framework API with Bookmark and Note models - ViewSets with user-scoped querysets and select_related for N+1 prevention - Create/List/Detail/Update/Delete endpoints - Batch delete operations - Unique constraint on user+book+page for bookmarks - IsOwner permission class for object-level access control - Full serializer validation (page > 0, non-empty content, duplicate check) - 30+ pytest-django tests covering CRUD, auth, filtering, edge cases - Frontend: React TypeScript components - AnnotationsContext with useReducer for state management - BookmarkList, NoteList, AddAnnotationForm, AnnotationsDashboard - Inline note editing with immediate save - Batch delete support - API client with JWT auto-refresh interceptors - Paginated query hook for infinite scroll support - Responsive CSS with loading/empty states - Infrastructure: Django project with custom User model, JWT auth, CORS - PostgreSQL database models with proper FK and indexes - Django admin configuration for all models
This commit is contained in:
@@ -0,0 +1 @@
|
||||
# management/__init__.py
|
||||
@@ -0,0 +1 @@
|
||||
# management/commands/__init__.py
|
||||
@@ -0,0 +1,134 @@
|
||||
"""
|
||||
Management command to seed sample book data for development and testing.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from books.models import Book, ReadingStatus
|
||||
|
||||
SAMPLE_BOOKS: list[dict[str, Any]] = [
|
||||
{
|
||||
"title": "The Great Gatsby",
|
||||
"author": "F. Scott Fitzgerald",
|
||||
"genre": "Classic Literature",
|
||||
"description": "A story of the mysteriously wealthy Jay Gatsby and his love for the beautiful Daisy Buchanan.",
|
||||
"reading_status": ReadingStatus.FINISHED,
|
||||
},
|
||||
{
|
||||
"title": "To Kill a Mockingbird",
|
||||
"author": "Harper Lee",
|
||||
"genre": "Classic Literature",
|
||||
"description": "The unforgettable novel of a childhood in a sleepy Southern town and the crisis of conscience that rocked it.",
|
||||
"reading_status": ReadingStatus.FINISHED,
|
||||
},
|
||||
{
|
||||
"title": "1984",
|
||||
"author": "George Orwell",
|
||||
"genre": "Science Fiction",
|
||||
"description": "A dystopian social science fiction novel and cautionary tale about the future of totalitarianism.",
|
||||
"reading_status": ReadingStatus.READING,
|
||||
},
|
||||
{
|
||||
"title": "Dune",
|
||||
"author": "Frank Herbert",
|
||||
"genre": "Science Fiction",
|
||||
"description": "Set on the desert planet Arrakis, it is one of the world's best-selling science fiction novels.",
|
||||
"reading_status": ReadingStatus.FINISHED,
|
||||
},
|
||||
{
|
||||
"title": "The Hobbit",
|
||||
"author": "J.R.R. Tolkien",
|
||||
"genre": "Fantasy",
|
||||
"description": "Bilbo Baggins is swept into a quest to reclaim the lost Dwarf Kingdom of Erebor from the fearsome dragon Smaug.",
|
||||
"reading_status": ReadingStatus.FINISHED,
|
||||
},
|
||||
{
|
||||
"title": "Pride and Prejudice",
|
||||
"author": "Jane Austen",
|
||||
"genre": "Romance",
|
||||
"description": "A romantic novel of manners that follows the character development of Elizabeth Bennet.",
|
||||
"reading_status": ReadingStatus.WANT_TO_READ,
|
||||
},
|
||||
{
|
||||
"title": "The Martian",
|
||||
"author": "Andy Weir",
|
||||
"genre": "Science Fiction",
|
||||
"description": "An astronaut becomes stranded alone on Mars and must find a way to signal that he is alive.",
|
||||
"reading_status": ReadingStatus.READING,
|
||||
},
|
||||
{
|
||||
"title": "The Catcher in the Rye",
|
||||
"author": "J.D. Salinger",
|
||||
"genre": "Classic Literature",
|
||||
"description": "The story of Holden Caulfield's experiences in New York City after being expelled from prep school.",
|
||||
"reading_status": ReadingStatus.DNF,
|
||||
},
|
||||
{
|
||||
"title": "The Alchemist",
|
||||
"author": "Paulo Coelho",
|
||||
"genre": "Philosophy",
|
||||
"description": "A young Andalusian shepherd follows his dream to find treasure at the Egyptian pyramids.",
|
||||
"reading_status": ReadingStatus.WANT_TO_READ,
|
||||
},
|
||||
{
|
||||
"title": "Neuromancer",
|
||||
"author": "William Gibson",
|
||||
"genre": "Science Fiction",
|
||||
"description": "The novel that launched the cyberpunk genre, following washed-up computer hacker Henry Case.",
|
||||
"reading_status": ReadingStatus.FINISHED,
|
||||
},
|
||||
{
|
||||
"title": "The Name of the Wind",
|
||||
"author": "Patrick Rothfuss",
|
||||
"genre": "Fantasy",
|
||||
"description": "The tale of the magically gifted young man who grows to be the most notorious wizard his world has ever seen.",
|
||||
"reading_status": ReadingStatus.READING,
|
||||
},
|
||||
{
|
||||
"title": "Gone Girl",
|
||||
"author": "Gillian Flynn",
|
||||
"genre": "Thriller",
|
||||
"description": "A mystery thriller about a wife's disappearance on the day of her fifth wedding anniversary.",
|
||||
"reading_status": ReadingStatus.FINISHED,
|
||||
},
|
||||
{
|
||||
"title": "Sapiens",
|
||||
"author": "Yuval Noah Harari",
|
||||
"genre": "Non-Fiction",
|
||||
"description": "A brief history of humankind, exploring how biology and history have defined us.",
|
||||
"reading_status": ReadingStatus.FINISHED,
|
||||
},
|
||||
{
|
||||
"title": "The Road",
|
||||
"author": "Cormac McCarthy",
|
||||
"genre": "Post-Apocalyptic",
|
||||
"description": "A father and his young son walk alone through burned America heading toward the coast.",
|
||||
"reading_status": ReadingStatus.WANT_TO_READ,
|
||||
},
|
||||
{
|
||||
"title": "The Three-Body Problem",
|
||||
"author": "Cixin Liu",
|
||||
"genre": "Science Fiction",
|
||||
"description": "The first novel in the Remembrance of Earth's Past trilogy, a blend of physics and alien contact.",
|
||||
"reading_status": ReadingStatus.READING,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
"""Seed the database with sample books."""
|
||||
|
||||
help = "Seeds the database with sample books for development and testing."
|
||||
|
||||
def handle(self, *args: Any, **options: Any) -> str | None:
|
||||
for i, book_data in enumerate(SAMPLE_BOOKS):
|
||||
Book.objects.get_or_create(
|
||||
title=book_data["title"],
|
||||
author=book_data["author"],
|
||||
defaults=book_data,
|
||||
)
|
||||
count = Book.objects.count()
|
||||
self.stdout.write(self.style.SUCCESS(f"Seeded {count} books into the database."))
|
||||
Reference in New Issue
Block a user