Files
thrillwiki_django_no_react/docs/park-detail-endpoint-documentation.md
pacnpal 0fd6dc2560 feat: Enhance Park Detail Endpoint with Media URL Service Integration
- Updated ParkDetailOutputSerializer to utilize MediaURLService for generating Cloudflare URLs and friendly URLs for park photos.
- Added support for multiple lookup methods (ID and slug) in the park detail endpoint.
- Improved documentation for the park detail endpoint, including request properties and response structure.
- Created MediaURLService for generating SEO-friendly URLs and handling Cloudflare image URLs.
- Comprehensive updates to frontend documentation to reflect new endpoint capabilities and usage examples.
- Added detailed park detail endpoint documentation, including request and response structures, field descriptions, and usage examples.
2025-08-31 16:45:47 -04:00

511 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Park Detail Endpoint - Complete Documentation
## Endpoint Overview
**URL:** `GET /api/v1/parks/{identifier}/`
**Description:** Retrieve comprehensive park details including location, photos, areas, rides, and company information.
**Authentication:** None required (public endpoint)
**Supports Multiple Lookup Methods:**
- By ID: `/api/v1/parks/123/`
- By current slug: `/api/v1/parks/cedar-point/`
- By historical slug: `/api/v1/parks/old-cedar-point-name/`
## Request Properties
### Path Parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `identifier` | string | Yes | Park ID (integer) or slug (string). Supports current and historical slugs. |
### Query Parameters
**None required** - This endpoint returns full park details by default without any query parameters.
### Request Headers
| Header | Required | Description |
|--------|----------|-------------|
| `Accept` | No | `application/json` (default) |
| `Content-Type` | No | Not applicable for GET requests |
## Response Structure
### Success Response (200 OK)
```json
{
"id": 1,
"name": "Cedar Point",
"slug": "cedar-point",
"status": "OPERATING",
"description": "America's Roller Coast",
"park_type": "THEME_PARK",
// Dates and Operations
"opening_date": "1870-01-01",
"closing_date": null,
"operating_season": "May - October",
"size_acres": 364.0,
"website": "https://cedarpoint.com",
// Statistics
"average_rating": 4.5,
"coaster_count": 17,
"ride_count": 70,
// Location Information
"location": {
"id": 1,
"latitude": 41.4793,
"longitude": -82.6833,
"street_address": "1 Cedar Point Dr",
"city": "Sandusky",
"state": "Ohio",
"country": "United States",
"continent": "North America",
"postal_code": "44870",
"formatted_address": "1 Cedar Point Dr, Sandusky, OH 44870, United States"
},
// Company Information
"operator": {
"id": 1,
"name": "Cedar Fair",
"slug": "cedar-fair",
"roles": ["OPERATOR"],
"description": "Leading amusement park operator",
"website": "https://cedarfair.com",
"founded_year": 1983
},
"property_owner": {
"id": 1,
"name": "Cedar Fair",
"slug": "cedar-fair",
"roles": ["OPERATOR", "PROPERTY_OWNER"],
"description": "Leading amusement park operator",
"website": "https://cedarfair.com",
"founded_year": 1983
},
// Park Areas/Themed Sections
"areas": [
{
"id": 1,
"name": "Frontier Town",
"slug": "frontier-town",
"description": "Wild West themed area"
},
{
"id": 2,
"name": "Millennium Island",
"slug": "millennium-island",
"description": "Home to Millennium Force"
}
],
// Photo Information
"photos": [
{
"id": 456,
"image_url": "https://imagedelivery.net/account-hash/def789ghi012/public",
"image_variants": {
"thumbnail": "https://imagedelivery.net/account-hash/def789ghi012/thumbnail",
"medium": "https://imagedelivery.net/account-hash/def789ghi012/medium",
"large": "https://imagedelivery.net/account-hash/def789ghi012/large",
"public": "https://imagedelivery.net/account-hash/def789ghi012/public"
},
"friendly_urls": {
"thumbnail": "/parks/cedar-point/photos/beautiful-park-entrance-456-thumbnail.jpg",
"medium": "/parks/cedar-point/photos/beautiful-park-entrance-456-medium.jpg",
"large": "/parks/cedar-point/photos/beautiful-park-entrance-456-large.jpg",
"public": "/parks/cedar-point/photos/beautiful-park-entrance-456.jpg"
},
"caption": "Beautiful park entrance",
"alt_text": "Cedar Point main entrance with flags",
"is_primary": true
}
],
// Primary Photo (designated main photo)
"primary_photo": {
"id": 456,
"image_url": "https://imagedelivery.net/account-hash/def789ghi012/public",
"image_variants": {
"thumbnail": "https://imagedelivery.net/account-hash/def789ghi012/thumbnail",
"medium": "https://imagedelivery.net/account-hash/def789ghi012/medium",
"large": "https://imagedelivery.net/account-hash/def789ghi012/large",
"public": "https://imagedelivery.net/account-hash/def789ghi012/public"
},
"caption": "Beautiful park entrance",
"alt_text": "Cedar Point main entrance with flags"
},
// Banner Image (for hero sections)
"banner_image": {
"id": 456,
"image_url": "https://imagedelivery.net/account-hash/def789ghi012/public",
"image_variants": {
"thumbnail": "https://imagedelivery.net/account-hash/def789ghi012/thumbnail",
"medium": "https://imagedelivery.net/account-hash/def789ghi012/medium",
"large": "https://imagedelivery.net/account-hash/def789ghi012/large",
"public": "https://imagedelivery.net/account-hash/def789ghi012/public"
},
"caption": "Beautiful park entrance",
"alt_text": "Cedar Point main entrance with flags",
"is_fallback": false
},
// Card Image (for listings/cards)
"card_image": {
"id": 456,
"image_url": "https://imagedelivery.net/account-hash/def789ghi012/public",
"image_variants": {
"thumbnail": "https://imagedelivery.net/account-hash/def789ghi012/thumbnail",
"medium": "https://imagedelivery.net/account-hash/def789ghi012/medium",
"large": "https://imagedelivery.net/account-hash/def789ghi012/large",
"public": "https://imagedelivery.net/account-hash/def789ghi012/public"
},
"caption": "Beautiful park entrance",
"alt_text": "Cedar Point main entrance with flags",
"is_fallback": false
},
// Frontend URL
"url": "https://thrillwiki.com/parks/cedar-point/",
// Metadata
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-15T12:30:00Z"
}
```
### Error Responses
#### 404 Not Found
```json
{
"detail": "Park not found"
}
```
#### 500 Internal Server Error
```json
{
"detail": "Internal server error"
}
```
## Field Descriptions
### Core Park Information
| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Unique park identifier |
| `name` | string | Official park name |
| `slug` | string | URL-friendly identifier |
| `status` | string | Operational status (see Status Values) |
| `description` | string | Park description/tagline |
| `park_type` | string | Park category (see Park Type Values) |
### Operational Details
| Field | Type | Description |
|-------|------|-------------|
| `opening_date` | date | Park opening date (YYYY-MM-DD) |
| `closing_date` | date | Park closing date (null if still operating) |
| `operating_season` | string | Seasonal operation description |
| `size_acres` | decimal | Park size in acres |
| `website` | string | Official park website URL |
### Statistics
| Field | Type | Description |
|-------|------|-------------|
| `average_rating` | decimal | Average user rating (1-10 scale) |
| `coaster_count` | integer | Number of roller coasters |
| `ride_count` | integer | Total number of rides |
### Location Object
| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Location record ID |
| `latitude` | float | Geographic latitude |
| `longitude` | float | Geographic longitude |
| `street_address` | string | Street address |
| `city` | string | City name |
| `state` | string | State/province |
| `country` | string | Country name |
| `continent` | string | Continent name |
| `postal_code` | string | ZIP/postal code |
| `formatted_address` | string | Complete formatted address |
### Company Objects (Operator/Property Owner)
| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Company ID |
| `name` | string | Company name |
| `slug` | string | URL-friendly identifier |
| `roles` | array | Company roles (OPERATOR, PROPERTY_OWNER, etc.) |
| `description` | string | Company description |
| `website` | string | Company website |
| `founded_year` | integer | Year company was founded |
### Area Objects
| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Area ID |
| `name` | string | Area/section name |
| `slug` | string | URL-friendly identifier |
| `description` | string | Area description |
### Photo Objects
| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Photo ID |
| `image_url` | string | Base Cloudflare image URL |
| `image_variants` | object | Available image sizes/transformations |
| `caption` | string | Photo caption |
| `alt_text` | string | Accessibility alt text |
| `is_primary` | boolean | Whether this is the primary photo |
| `is_fallback` | boolean | Whether this is a fallback image |
### Image Variants Object
| Field | Type | Description |
|-------|------|-------------|
| `thumbnail` | string | Small thumbnail URL (150x150) |
| `medium` | string | Medium size URL (500x500) |
| `large` | string | Large size URL (1200x1200) |
| `public` | string | Full size public URL |
## Enumerated Values
### Status Values
| Value | Description |
|-------|-------------|
| `OPERATING` | Currently operating |
| `CLOSED_TEMP` | Temporarily closed |
| `CLOSED_PERM` | Permanently closed |
| `UNDER_CONSTRUCTION` | Under construction |
| `DEMOLISHED` | Demolished |
| `RELOCATED` | Relocated |
### Park Type Values
| Value | Description |
|-------|-------------|
| `THEME_PARK` | Theme park |
| `AMUSEMENT_PARK` | Amusement park |
| `WATER_PARK` | Water park |
| `FAMILY_ENTERTAINMENT_CENTER` | Family entertainment center |
| `CARNIVAL` | Carnival |
| `FAIR` | Fair |
| `PIER` | Pier |
| `BOARDWALK` | Boardwalk |
| `SAFARI_PARK` | Safari park |
| `ZOO` | Zoo |
| `OTHER` | Other |
## Usage Examples
### JavaScript/TypeScript
```typescript
// Fetch by ID
const parkById = await fetch('/api/v1/parks/123/');
const parkData = await parkById.json();
// Fetch by current slug
const parkBySlug = await fetch('/api/v1/parks/cedar-point/');
const parkData2 = await parkBySlug.json();
// Fetch by historical slug
const parkByHistoricalSlug = await fetch('/api/v1/parks/old-name/');
const parkData3 = await parkByHistoricalSlug.json();
// Access different image sizes
const thumbnailUrl = parkData.primary_photo?.image_variants.thumbnail;
const fullSizeUrl = parkData.primary_photo?.image_variants.public;
```
### Python
```python
import requests
# Fetch park details
response = requests.get('https://api.thrillwiki.com/api/v1/parks/cedar-point/')
park_data = response.json()
# Access park information
park_name = park_data['name']
location = park_data['location']
operator = park_data['operator']
photos = park_data['photos']
```
### cURL
```bash
# Fetch by slug
curl -X GET "https://api.thrillwiki.com/api/v1/parks/cedar-point/" \
-H "Accept: application/json"
# Fetch by ID
curl -X GET "https://api.thrillwiki.com/api/v1/parks/123/" \
-H "Accept: application/json"
```
## Related Endpoints
- **Park List:** `GET /api/v1/parks/` - List parks with filtering
- **Park Photos:** `GET /api/v1/parks/{id}/photos/` - Manage park photos
- **Park Areas:** `GET /api/v1/parks/{id}/areas/` - Park themed areas
- **Park Image Settings:** `PATCH /api/v1/parks/{id}/image-settings/` - Set banner/card images
## Photo Handling Details
### Photo Upload vs Display Distinction
**Important**: You can upload unlimited photos per park, but the park detail endpoint shows only the 10 most relevant photos for performance optimization.
#### **Photo Upload Capacity**
- **No Upload Limit**: Upload unlimited photos per park via `POST /api/v1/parks/{park_id}/photos/`
- **Storage**: All photos stored in database and Cloudflare Images
- **Approval System**: Each photo goes through moderation (`is_approved` field)
- **Photo Types**: Categorize photos (banner, card, gallery, etc.)
- **Bulk Upload**: Support for multiple photo uploads
#### **Display Limit (Detail Endpoint)**
- **10 Photo Limit**: Only applies to this park detail endpoint response
- **Smart Selection**: Shows 10 most relevant photos using intelligent ordering:
1. **Primary photos first** (`-is_primary`)
2. **Newest photos next** (`-created_at`)
3. **Only approved photos** (`is_approved=True`)
### Complete Photo Access
#### **All Photos Available Via Dedicated Endpoint**
```
GET /api/v1/parks/{park_id}/photos/
```
- **No Limit**: Returns all uploaded photos for the park
- **Pagination**: Supports pagination for large photo collections
- **Filtering**: Filter by photo type, approval status, etc.
- **Full Management**: Complete CRUD operations for all photos
#### **Photo URL Structure Per Park**
**Maximum Possible URLs per park:**
- **General photos**: 10 photos × 4 variants = **40 URLs**
- **Primary photo**: 1 photo × 4 variants = **4 URLs**
- **Banner image**: 1 photo × 4 variants = **4 URLs**
- **Card image**: 1 photo × 4 variants = **4 URLs**
- **Total Maximum**: **52 photo URLs per park**
**Each photo includes 4 Cloudflare transformation URLs:**
1. **`thumbnail`**: Optimized for small previews (150x150)
2. **`medium`**: Medium resolution for general use (500x500)
3. **`large`**: High resolution for detailed viewing (1200x1200)
4. **`public`**: Original/full size image
#### **Practical Example**
A park could have:
- **50 uploaded photos** (all stored in system)
- **30 approved photos** (available for public display)
- **10 photos shown** in park detail endpoint (most relevant)
- **All 30 approved photos** accessible via `/api/v1/parks/{id}/photos/`
#### **Frontend Implementation Strategy**
```javascript
// Get park with essential photos (fast initial load)
const park = await fetch('/api/v1/parks/cedar-point/');
// Get complete photo gallery when needed (e.g., photo gallery page)
const allPhotos = await fetch('/api/v1/parks/123/photos/?page_size=50');
```
### Friendly URLs for Photos
**NEW FEATURE**: Each photo now includes both Cloudflare URLs and SEO-friendly URLs.
#### **URL Structure**
```
/parks/{park-slug}/photos/{caption-slug}-{photo-id}-{variant}.jpg
```
**Examples:**
- `/parks/cedar-point/photos/beautiful-park-entrance-456.jpg` (public/original)
- `/parks/cedar-point/photos/beautiful-park-entrance-456-thumbnail.jpg`
- `/parks/cedar-point/photos/beautiful-park-entrance-456-medium.jpg`
- `/parks/cedar-point/photos/beautiful-park-entrance-456-large.jpg`
#### **Benefits**
- **SEO Optimized**: Descriptive URLs improve search engine ranking
- **User Friendly**: URLs are readable and meaningful
- **Consistent**: Follows predictable pattern across all photos
- **Backwards Compatible**: Original Cloudflare URLs still available
#### **Implementation**
Each photo object now includes both URL types:
```json
{
"id": 456,
"image_url": "https://imagedelivery.net/account-hash/def789ghi012/public",
"image_variants": {
"thumbnail": "https://imagedelivery.net/account-hash/def789ghi012/thumbnail",
"medium": "https://imagedelivery.net/account-hash/def789ghi012/medium",
"large": "https://imagedelivery.net/account-hash/def789ghi012/large",
"public": "https://imagedelivery.net/account-hash/def789ghi012/public"
},
"friendly_urls": {
"thumbnail": "/parks/cedar-point/photos/beautiful-park-entrance-456-thumbnail.jpg",
"medium": "/parks/cedar-point/photos/beautiful-park-entrance-456-medium.jpg",
"large": "/parks/cedar-point/photos/beautiful-park-entrance-456-large.jpg",
"public": "/parks/cedar-point/photos/beautiful-park-entrance-456.jpg"
},
"caption": "Beautiful park entrance",
"alt_text": "Cedar Point main entrance with flags"
}
```
### Photo Management Features
- **Primary Photo**: Designate which photo represents the park
- **Banner/Card Images**: Set specific photos for different UI contexts
- **Fallback Logic**: Banner and card images automatically fallback to latest approved photo if not explicitly set
- **Approval Workflow**: Moderate photos before public display
- **Photo Metadata**: Each photo includes caption, alt text, and categorization
- **Dual URL System**: Both Cloudflare and friendly URLs provided for maximum flexibility
## Performance Notes
- Response includes optimized database queries with `select_related` and `prefetch_related`
- Photos limited to 10 most recent approved photos for optimal response size
- Image variants are pre-computed Cloudflare transformations for fast delivery
- Historical slug lookup may require additional database queries
- Smart photo selection ensures most relevant photos are included
## Caching
- No caching implemented at endpoint level
- Cloudflare images are cached at CDN level
- Consider implementing Redis caching for frequently accessed parks
## Rate Limiting
- No rate limiting currently implemented
- Public endpoint accessible without authentication
- Consider implementing rate limiting for production use