Files
pacnpal d504d41de2 feat: complete monorepo structure with frontend and shared resources
- Add complete backend/ directory with full Django application
- Add frontend/ directory with Vite + TypeScript setup ready for Next.js
- Add comprehensive shared/ directory with:
  - Complete documentation and memory-bank archives
  - Media files and avatars (letters, park/ride images)
  - Deployment scripts and automation tools
  - Shared types and utilities
- Add architecture/ directory with migration guides
- Configure pnpm workspace for monorepo development
- Update .gitignore to exclude .django_tailwind_cli/ build artifacts
- Preserve all historical documentation in shared/docs/memory-bank/
- Set up proper structure for full-stack development with shared resources
2025-08-23 18:40:07 -04:00

7.4 KiB

Data Documentation

Database Schema

Core Models

Parks

CREATE TABLE parks_park (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    slug VARCHAR(255) UNIQUE NOT NULL,
    description TEXT,
    status VARCHAR(20) DEFAULT 'OPERATING',
    opening_date DATE,
    closing_date DATE,
    operating_season VARCHAR(255),
    size_acres DECIMAL(10,2),
    website VARCHAR(200),
    average_rating DECIMAL(3,2),
    ride_count INTEGER,
    coaster_count INTEGER,
    owner_id INTEGER REFERENCES companies_company(id),
    created_at TIMESTAMP,
    updated_at TIMESTAMP
);

Rides

CREATE TABLE rides_ride (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    slug VARCHAR(255) NOT NULL,
    description TEXT,
    status VARCHAR(20),
    park_id INTEGER REFERENCES parks_park(id),
    area_id INTEGER REFERENCES parks_parkarea(id),
    manufacturer_id INTEGER REFERENCES companies_company(id),
    designer_id INTEGER REFERENCES designers_designer(id),
    opening_date DATE,
    closing_date DATE,
    height_requirement INTEGER,
    ride_type VARCHAR(50),
    thrill_rating INTEGER,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    UNIQUE(park_id, slug)
);

Reviews

CREATE TABLE reviews_review (
    id SERIAL PRIMARY KEY,
    content TEXT NOT NULL,
    rating DECIMAL(3,2),
    status VARCHAR(20),
    author_id INTEGER REFERENCES auth_user(id),
    content_type_id INTEGER REFERENCES django_content_type(id),
    object_id INTEGER,
    created_at TIMESTAMP,
    updated_at TIMESTAMP
);

Entity Relationships

erDiagram
    Park ||--o{ ParkArea : "contains"
    Park ||--o{ Ride : "has"
    Park ||--o{ Photo : "has"
    Park ||--o{ Review : "receives"
    ParkArea ||--o{ Ride : "contains"
    Ride ||--o{ Photo : "has"
    Ride ||--o{ Review : "receives"
    Company ||--o{ Park : "owns"
    Company ||--o{ Ride : "manufactures"
    Designer ||--o{ Ride : "designs"
    User ||--o{ Review : "writes"

Data Models

Content Models

Park Model

  • Core information about theme parks
  • Location data through GenericRelation
  • Media attachments
  • Historical tracking
  • Owner relationship

Ride Model

  • Technical specifications
  • Park and area relationships
  • Manufacturer and designer links
  • Operation status tracking
  • Safety requirements

Review Model

  • Generic foreign key for flexibility
  • Rating system
  • Media attachments
  • Moderation status
  • Author tracking

Supporting Models

Location Model

class Location(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey()
    
    address = models.CharField(max_length=255)
    city = models.CharField(max_length=100)
    state = models.CharField(max_length=100)
    country = models.CharField(max_length=100)
    postal_code = models.CharField(max_length=20)
    latitude = models.DecimalField(max_digits=9, decimal_places=6)
    longitude = models.DecimalField(max_digits=9, decimal_places=6)

Media Model

class Photo(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey()
    
    file = models.ImageField(upload_to='photos/')
    caption = models.CharField(max_length=255)
    taken_at = models.DateTimeField(null=True)
    uploaded_at = models.DateTimeField(auto_now_add=True)

Storage Strategies

Database Storage

PostgreSQL Configuration

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'thrillwiki',
        'CONN_MAX_AGE': 60,
        'OPTIONS': {
            'client_encoding': 'UTF8',
        },
    }
}

Indexing Strategy

-- Performance indexes
CREATE INDEX idx_park_slug ON parks_park(slug);
CREATE INDEX idx_ride_slug ON rides_ride(slug);
CREATE INDEX idx_review_content_type ON reviews_review(content_type_id, object_id);

File Storage

Media Storage

# Media storage configuration
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

# File upload handlers
FILE_UPLOAD_HANDLERS = [
    'django.core.files.uploadhandler.MemoryFileUploadHandler',
    'django.core.files.uploadhandler.TemporaryFileUploadHandler',
]

Directory Structure

media/
├── photos/
│   ├── parks/
│   ├── rides/
│   └── reviews/
├── avatars/
└── documents/

Caching Strategy

Cache Configuration

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.redis.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
        }
    }
}

Cache Keys

# Cache key patterns
CACHE_KEYS = {
    'park_detail': 'park:{slug}',
    'ride_list': 'park:{park_slug}:rides',
    'review_count': 'content:{type}:{id}:reviews',
}

Data Migration

Migration Strategy

  1. Schema migrations via Django
  2. Data migrations for model changes
  3. Content migrations for large updates

Example Migration

# migrations/0002_add_park_status.py
from django.db import migrations, models

class Migration(migrations.Migration):
    dependencies = [
        ('parks', '0001_initial'),
    ]
    
    operations = [
        migrations.AddField(
            model_name='park',
            name='status',
            field=models.CharField(
                max_length=20,
                choices=[
                    ('OPERATING', 'Operating'),
                    ('CLOSED', 'Closed'),
                ],
                default='OPERATING'
            ),
        ),
    ]

Data Protection

Backup Strategy

  1. Daily database backups
  2. Media files backup
  3. Retention policy management

Backup Configuration

# backup settings
BACKUP_ROOT = os.path.join(BASE_DIR, 'backups')
BACKUP_RETENTION_DAYS = 30
BACKUP_COMPRESSION = True

Data Validation

Model Validation

class Park(models.Model):
    def clean(self):
        if self.closing_date and self.opening_date:
            if self.closing_date < self.opening_date:
                raise ValidationError({
                    'closing_date': 'Closing date cannot be before opening date'
                })

Form Validation

class RideForm(forms.ModelForm):
    def clean_height_requirement(self):
        height = self.cleaned_data['height_requirement']
        if height and height < 0:
            raise forms.ValidationError('Height requirement cannot be negative')
        return height

Data Access Patterns

QuerySet Optimization

# Optimized query pattern
Park.objects.select_related('owner')\
    .prefetch_related('rides', 'areas')\
    .filter(status='OPERATING')

Caching Pattern

def get_park_detail(slug):
    cache_key = f'park:{slug}'
    park = cache.get(cache_key)
    if not park:
        park = Park.objects.get(slug=slug)
        cache.set(cache_key, park, timeout=3600)
    return park

Monitoring and Metrics

Database Metrics

  • Query performance
  • Cache hit rates
  • Storage usage
  • Connection pool status

Collection Configuration

LOGGING = {
    'handlers': {
        'db_log': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': 'logs/db.log',
        },
    },
}