mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 13:31:08 -05:00
Add comprehensive system architecture and feature documentation for ThrillWiki
This commit is contained in:
327
memory-bank/documentation/Data.md
Normal file
327
memory-bank/documentation/Data.md
Normal file
@@ -0,0 +1,327 @@
|
||||
# Data Documentation
|
||||
|
||||
## Database Schema
|
||||
|
||||
### Core Models
|
||||
|
||||
#### Parks
|
||||
```sql
|
||||
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
|
||||
```sql
|
||||
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
|
||||
```sql
|
||||
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
|
||||
|
||||
```mermaid
|
||||
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
|
||||
```python
|
||||
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
|
||||
```python
|
||||
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
|
||||
```python
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql',
|
||||
'NAME': 'thrillwiki',
|
||||
'CONN_MAX_AGE': 60,
|
||||
'OPTIONS': {
|
||||
'client_encoding': 'UTF8',
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Indexing Strategy
|
||||
```sql
|
||||
-- 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
|
||||
```python
|
||||
# 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
|
||||
```python
|
||||
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
|
||||
```python
|
||||
# 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
|
||||
```python
|
||||
# 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
|
||||
```python
|
||||
# backup settings
|
||||
BACKUP_ROOT = os.path.join(BASE_DIR, 'backups')
|
||||
BACKUP_RETENTION_DAYS = 30
|
||||
BACKUP_COMPRESSION = True
|
||||
```
|
||||
|
||||
## Data Validation
|
||||
|
||||
### Model Validation
|
||||
```python
|
||||
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
|
||||
```python
|
||||
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
|
||||
```python
|
||||
# Optimized query pattern
|
||||
Park.objects.select_related('owner')\
|
||||
.prefetch_related('rides', 'areas')\
|
||||
.filter(status='OPERATING')
|
||||
```
|
||||
|
||||
### Caching Pattern
|
||||
```python
|
||||
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
|
||||
```python
|
||||
LOGGING = {
|
||||
'handlers': {
|
||||
'db_log': {
|
||||
'level': 'DEBUG',
|
||||
'class': 'logging.handlers.RotatingFileHandler',
|
||||
'filename': 'logs/db.log',
|
||||
},
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user