feat: add passkey authentication and enhance user preferences - Add passkey login security event type with fingerprint icon - Include request and site context in email confirmation for backend - Add user_id exact match filter to prevent incorrect user lookups - Enable PATCH method for updating user preferences via API - Add moderation_preferences support to user settings - Optimize ticket queries with select_related and prefetch_related This commit introduces passkey authentication tracking, improves user profile filtering accuracy, and extends the preferences API to support updates. Query optimizations reduce database hits for ticket listings.
ThrillWiki Backend
Django application powering ThrillWiki - a comprehensive theme park and roller coaster information system.
Architecture
ThrillWiki is a Django monolith with HTMX-driven templates, providing:
- Server-side rendering with Django templates
- HTMX for dynamic partial updates without full page reloads
- REST API for programmatic access (mobile apps, integrations)
- Alpine.js for minimal client-side state (form validation, UI toggles)
backend/
├── apps/ # Django applications
│ ├── accounts/ # User authentication and profiles
│ ├── api/v1/ # REST API endpoints
│ ├── core/ # Shared utilities, managers, services
│ ├── location/ # Geographic data and services
│ ├── media/ # Cloudflare Images integration
│ ├── moderation/ # Content moderation workflows
│ ├── parks/ # Theme park models and views
│ └── rides/ # Ride information and statistics
├── config/ # Django configuration
│ ├── django/ # Environment-specific settings
│ │ ├── base.py # Core settings
│ │ ├── local.py # Development overrides
│ │ ├── production.py # Production overrides
│ │ └── test.py # Test overrides
│ └── settings/ # Modular settings modules
│ ├── cache.py # Redis caching
│ ├── database.py # Database and GeoDjango
│ ├── email.py # Email configuration
│ ├── logging.py # Logging setup
│ ├── rest_framework.py # DRF, JWT, CORS
│ ├── security.py # Security headers
│ └── storage.py # Static/media files
├── templates/ # Django templates with HTMX
│ ├── components/ # Reusable UI components
│ ├── htmx/ # HTMX partial templates
│ └── layouts/ # Base layout templates
├── static/ # Static assets
└── tests/ # Test files
Technology Stack
| Technology | Version | Purpose |
|---|---|---|
| Django | 5.2.8+ | Web framework (security patched) |
| Django REST Framework | 3.15.2+ | API framework (security patched) |
| HTMX | 1.20.0+ | Dynamic UI updates |
| Alpine.js | 3.x | Minimal client-side state |
| Tailwind CSS | 3.x | Utility-first styling |
| PostgreSQL/PostGIS | 14+ | Database with geospatial support |
| Redis | 6+ | Caching and sessions |
| Celery | 5.5+ | Background task processing |
| UV | Latest | Python package management |
Quick Start
Prerequisites
- Python 3.13+
- uv package manager
- PostgreSQL 14+ with PostGIS extension
- Redis 6+
Setup
-
Install dependencies
cd backend uv sync --frozen # Use locked versions for reproducibility # Or: uv sync # Allow updates within version constraints -
Environment configuration
cp .env.example .env # Edit .env with your settings -
Database setup
uv run manage.py migrate uv run manage.py createsuperuser -
Start development server
uv run manage.py runserver
The application will be available at http://localhost:8000.
HTMX Patterns
ThrillWiki uses HTMX for server-driven interactivity. Key patterns:
Partial Templates
Views render partial templates for HTMX requests:
# In views.py
def park_list(request):
parks = Park.objects.optimized_for_list()
template = "parks/partials/park_list.html" if request.htmx else "parks/park_list.html"
return render(request, template, {"parks": parks})
HX-Trigger Events
Cross-component communication via custom events:
<!-- Trigger event after action -->
<button hx-post="/parks/1/favorite/"
hx-trigger="click"
hx-swap="none"
hx-headers='{"HX-Trigger-After-Settle": "parkFavorited"}'>
Favorite
</button>
<!-- Listen for event -->
<div hx-get="/parks/favorites/"
hx-trigger="parkFavorited from:body">
<!-- Updated on event -->
</div>
Loading Indicators
Skeleton loaders for better UX:
<div hx-get="/parks/" hx-trigger="load" hx-indicator="#loading">
<div id="loading" class="htmx-indicator">
{% include "components/skeleton_loader.html" %}
</div>
</div>
Field-Level Validation
Real-time form validation:
<input name="email"
hx-post="/validate/email/"
hx-trigger="blur changed delay:500ms"
hx-target="next .error-message">
<span class="error-message"></span>
See HTMX Patterns for complete documentation.
Hybrid API/HTML Endpoints
Many views serve dual purposes through content negotiation:
class ParkDetailView(HybridViewMixin, DetailView):
"""
Returns HTML for browser requests, JSON for API requests.
Browser: GET /parks/cedar-point/ -> HTML template
API: GET /api/v1/parks/cedar-point/ -> JSON response
"""
model = Park
template_name = "parks/park_detail.html"
serializer_class = ParkSerializer
This approach:
- Reduces code duplication
- Ensures API and web views stay in sync
- Supports both HTMX partials and JSON responses
Configuration
Settings Architecture
ThrillWiki uses modular settings for maintainability:
config/
├── django/ # Environment-specific settings
│ ├── base.py # Core settings (imports modular settings)
│ ├── local.py # Development overrides
│ ├── production.py # Production overrides
│ └── test.py # Test overrides
├── settings/ # Modular settings
│ ├── cache.py # Redis caching
│ ├── database.py # Database and GeoDjango
│ ├── email.py # Email configuration
│ ├── logging.py # Logging setup
│ ├── rest_framework.py # DRF, JWT, CORS
│ ├── secrets.py # Secret management
│ ├── security.py # Security headers
│ ├── storage.py # Static/media files
│ ├── third_party.py # Allauth, Celery, etc.
│ └── validation.py # Settings validation
└── celery.py # Celery configuration
Validate configuration with:
uv run manage.py validate_settings
Environment Variables
Key environment variables:
| Variable | Description | Required |
|---|---|---|
SECRET_KEY |
Django secret key | Yes |
DEBUG |
Debug mode (True/False) | Yes |
DATABASE_URL |
PostgreSQL connection URL | Yes |
REDIS_URL |
Redis connection URL | Production |
DJANGO_SETTINGS_MODULE |
Settings module to use | Yes |
See Environment Variables for complete reference.
Apps Overview
Core Apps
| App | Description |
|---|---|
| accounts | User authentication, profiles, social auth (Google, Discord) |
| parks | Theme park models, views, and operations |
| rides | Ride models, coaster statistics, ride history |
| core | Shared utilities, managers, services, middleware |
Support Apps
| App | Description |
|---|---|
| api/v1 | REST API endpoints with OpenAPI documentation |
| moderation | Content moderation workflows and queue |
| location | Geographic data, geocoding, map services |
| media | Cloudflare Images integration |
API Endpoints
Base URL: http://localhost:8000/api/v1/
Interactive Documentation
- Swagger UI:
/api/docs/ - ReDoc:
/api/redoc/ - OpenAPI Schema:
/api/schema/
Core Endpoints
| Endpoint | Description |
|---|---|
/api/v1/auth/ |
Authentication (login, signup, social auth) |
/api/v1/parks/ |
Theme park CRUD and filtering |
/api/v1/rides/ |
Ride CRUD and filtering |
/api/v1/accounts/ |
User profile and settings |
/api/v1/maps/ |
Map data and location services |
/api/v1/health/ |
Health check endpoints |
See API Documentation for complete reference.
Testing
# Run all tests
uv run manage.py test
# Run specific app tests
uv run manage.py test apps.parks
uv run manage.py test apps.rides
# Run with coverage
uv run coverage run manage.py test
uv run coverage report
# Run accessibility tests
uv run manage.py test backend.tests.accessibility
Management Commands
ThrillWiki provides numerous management commands for development, deployment, and maintenance.
Configuration & Validation
# Validate all settings and environment variables
uv run manage.py validate_settings
uv run manage.py validate_settings --strict # Treat warnings as errors
uv run manage.py validate_settings --json # JSON output
uv run manage.py validate_settings --secrets-only # Only validate secrets
# Validate state machine configurations
uv run manage.py validate_state_machines
# List all FSM transition callbacks
uv run manage.py list_transition_callbacks
Database Operations
# Standard Django commands
uv run manage.py migrate
uv run manage.py makemigrations
uv run manage.py showmigrations
uv run manage.py createsuperuser
# Fix migration history issues
uv run manage.py fix_migrations
uv run manage.py fix_migration_history
# Reset database (DESTRUCTIVE - development only)
uv run manage.py reset_db
Cache Management
# Warm cache with frequently accessed data
uv run manage.py warm_cache
uv run manage.py warm_cache --parks-only
uv run manage.py warm_cache --rides-only
uv run manage.py warm_cache --metadata-only
uv run manage.py warm_cache --dry-run # Preview without caching
# Clear all caches
uv run manage.py clear_cache
Data Management
# Seed initial data (operators, manufacturers, etc.)
uv run manage.py seed_initial_data
# Create sample data for development
uv run manage.py create_sample_data
uv run manage.py create_sample_data --minimal # Quick setup
uv run manage.py create_sample_data --clear # Clear existing first
# Seed sample parks and rides
uv run manage.py seed_sample_data
# Seed test submissions for moderation
uv run manage.py seed_submissions
# Seed API test data
uv run manage.py seed_data
# Update park statistics (ride counts, ratings)
uv run manage.py update_park_counts
# Update ride rankings
uv run manage.py update_ride_rankings
User & Authentication
# Create test users
uv run manage.py create_test_users
# Delete user and all related data
uv run manage.py delete_user <username>
# Setup user groups and permissions
uv run manage.py setup_groups
# Setup Django sites framework
uv run manage.py setup_site
# Social authentication setup
uv run manage.py setup_social_auth
uv run manage.py setup_social_providers
uv run manage.py create_social_apps
uv run manage.py check_social_apps
uv run manage.py fix_social_apps
uv run manage.py reset_social_apps
uv run manage.py reset_social_auth
uv run manage.py cleanup_social_auth
uv run manage.py update_social_apps_sites
uv run manage.py verify_discord_settings
uv run manage.py test_discord_auth
uv run manage.py check_all_social_tables
uv run manage.py setup_social_auth_admin
# Avatar management
uv run manage.py generate_letter_avatars
uv run manage.py regenerate_avatars
Content & Media
# Static file management
uv run manage.py collectstatic
uv run manage.py optimize_static # Minify and compress
# Media file management (in shared/media/)
uv run manage.py download_photos
uv run manage.py move_photos
uv run manage.py fix_photo_paths
Trending & Discovery
# Calculate trending content
uv run manage.py calculate_trending
uv run manage.py update_trending
uv run manage.py test_trending
# Calculate new content for discovery
uv run manage.py calculate_new_content
Testing & Development
# Run development server with auto-reload
uv run manage.py rundev
# Setup development environment
uv run manage.py setup_dev
# Test location services
uv run manage.py test_location
# Test FSM transition callbacks
uv run manage.py test_transition_callbacks
# Analyze FSM transitions
uv run manage.py analyze_transitions
# Cleanup test data
uv run manage.py cleanup_test_data
Security & Auditing
# Run security audit
uv run manage.py security_audit
Command Categories
| Category | Commands |
|---|---|
| Configuration | validate_settings, validate_state_machines, list_transition_callbacks |
| Database | migrate, makemigrations, reset_db, fix_migrations |
| Cache | warm_cache, clear_cache |
| Data | seed_initial_data, create_sample_data, update_park_counts, update_ride_rankings |
| Users | create_test_users, delete_user, setup_groups, setup_social_auth |
| Media | collectstatic, optimize_static, download_photos, move_photos |
| Trending | calculate_trending, update_trending, calculate_new_content |
| Development | rundev, setup_dev, test_location, cleanup_test_data |
| Security | security_audit |
Common Workflows
Initial Setup
uv run manage.py migrate
uv run manage.py createsuperuser
uv run manage.py setup_groups
uv run manage.py seed_initial_data
uv run manage.py create_sample_data --minimal
uv run manage.py warm_cache
Development Reset
uv run manage.py reset_db
uv run manage.py migrate
uv run manage.py create_sample_data
uv run manage.py warm_cache
Production Deployment
uv run manage.py migrate
uv run manage.py collectstatic --noinput
uv run manage.py validate_settings --strict
uv run manage.py warm_cache
Cache Refresh
uv run manage.py clear_cache
uv run manage.py warm_cache
uv run manage.py calculate_trending
See Management Commands Reference for complete documentation.
Database
Entity Relationships
- Parks have Operators (required) and PropertyOwners (optional)
- Rides belong to Parks and may have Manufacturers/Designers
- Users can create submissions and moderate content
- Reviews are linked to Parks or Rides with user attribution
Migrations
# Create migrations
uv run manage.py makemigrations
# Apply migrations
uv run manage.py migrate
# Show migration status
uv run manage.py showmigrations
Security
Security features implemented:
- CORS configured for API access
- CSRF protection enabled
- JWT token authentication for API
- Session authentication for web
- Rate limiting on API endpoints
- Input validation and sanitization
- Security headers (HSTS, CSP, etc.)
Performance
Performance optimizations:
- Database query optimization with custom managers
- Redis caching for frequent queries
- Background tasks with Celery
- Connection pooling for database
- HTMX partials for minimal data transfer
Debugging
Development Tools
- Django Debug Toolbar - Request/response inspection
- Django Extensions - Additional management commands
- Silk profiler - Performance analysis
Logging
Logs are written to:
- Console (development)
- Files in
logs/directory (production) - Sentry (production, if configured)
Contributing
- Follow Django coding standards
- Write tests for new features
- Update documentation
- Run linting:
uv run ruff check . - Format code:
uv run black .
See Main Documentation for complete project documentation.