Archived
- Backend: Django 5 + DRF with accounts, documents, collections, and reading apps - Custom User model with email-based auth, JWT via SimpleJWT - Full CRUD viewsets with ModelSerializer + DRF routers - pytest, Ruff, drf-spectacular (OpenAPI), whitenoise - Dockerfile for production deployment - Frontend: React 18 + TypeScript + Vite - Lazy-loaded routes with ProtectedRoute/PublicRoute guards - Auth context with useReducer, token refresh interceptor - Pages: Login, Register, Library, Document Detail, Reader, Collections, Settings - Dark theme, responsive grid layout, Vite proxy to Django backend - Mobile: Expo SDK 51 + React Native + Expo Router - File-based routing with login, register, and library screens - AsyncStorage for token persistence, token refresh interceptor - Shared API types via @cloud-reader/shared workspace package - Shared: TypeScript types (API responses, auth, documents, etc.) - CI/CD: 3 independent GitHub Actions pipelines (backend, frontend, mobile)
41 lines
1.3 KiB
Python
41 lines
1.3 KiB
Python
from rest_framework import serializers
|
|
|
|
from .models import Document
|
|
|
|
|
|
class DocumentListSerializer(serializers.ModelSerializer[Document]):
|
|
cover_url = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = Document
|
|
fields = [
|
|
"id", "title", "author", "cover_url", "description",
|
|
"file_type", "file_size", "page_count", "tags",
|
|
"is_public", "uploaded_at", "updated_at",
|
|
]
|
|
read_only_fields = ["id", "uploaded_at", "updated_at"]
|
|
|
|
def get_cover_url(self, obj: Document) -> str | None:
|
|
return obj.cover_url
|
|
|
|
|
|
class DocumentDetailSerializer(DocumentListSerializer):
|
|
owner = serializers.PrimaryKeyRelatedField(read_only=True)
|
|
|
|
class Meta(DocumentListSerializer.Meta):
|
|
fields = DocumentListSerializer.Meta.fields + ["owner", "file"]
|
|
|
|
|
|
class DocumentUploadSerializer(serializers.ModelSerializer[Document]):
|
|
class Meta:
|
|
model = Document
|
|
fields = [
|
|
"title", "author", "description", "cover", "file",
|
|
"file_type", "file_size", "page_count", "tags", "is_public",
|
|
]
|
|
|
|
def validate_file_size(self, value: int) -> int:
|
|
max_size = 100 * 1024 * 1024 # 100 MB
|
|
if value > max_size:
|
|
raise serializers.ValidationError("File size must not exceed 100 MB.")
|
|
return value |