mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 08:11:08 -05:00
- Introduced Next.js integration guide for ThrillWiki API, detailing authentication, core domain APIs, data structures, and implementation patterns. - Documented the migration to Rich Choice Objects, highlighting changes for frontend developers and enhanced metadata availability. - Fixed the missing `get_by_slug` method in the Ride model, ensuring proper functionality of ride detail endpoints. - Created a test script to verify manufacturer syncing with ride models, ensuring data integrity across related models.
152 lines
5.2 KiB
Markdown
152 lines
5.2 KiB
Markdown
# Ride get_by_slug Method Implementation Fix
|
|
|
|
**Date:** September 15, 2025
|
|
**Issue:** AttributeError: type object 'Ride' has no attribute 'get_by_slug'
|
|
**Status:** ✅ RESOLVED
|
|
|
|
## Problem Description
|
|
|
|
The API endpoint `/api/v1/parks/{park_slug}/rides/{ride_slug}/` was failing with an AttributeError because the `Ride` model was missing the `get_by_slug` class method that was being called in the `ParkRideDetailAPIView`.
|
|
|
|
### Error Details
|
|
```
|
|
{"status":"error","error":{"code":"ATTRIBUTEERROR","message":"type object 'Ride' has no attribute 'get_by_slug'","details":null,"request_user":"AnonymousUser"},"data":null}
|
|
```
|
|
|
|
### Root Cause
|
|
The `ParkRideDetailAPIView` in `backend/apps/api/v1/parks/park_rides_views.py` was calling:
|
|
```python
|
|
ride, is_historical = Ride.get_by_slug(ride_slug, park=park)
|
|
```
|
|
|
|
However, the `Ride` model in `backend/apps/rides/models/rides.py` did not have this method implemented, while the `Park` model did have this pattern implemented.
|
|
|
|
## Solution Implemented
|
|
|
|
### 1. Added get_by_slug Class Method to Ride Model
|
|
|
|
Added the following method to the `Ride` class in `backend/apps/rides/models/rides.py`:
|
|
|
|
```python
|
|
@classmethod
|
|
def get_by_slug(cls, slug: str, park=None) -> tuple["Ride", bool]:
|
|
"""Get ride by current or historical slug, optionally within a specific park"""
|
|
from django.contrib.contenttypes.models import ContentType
|
|
from apps.core.history import HistoricalSlug
|
|
|
|
# Build base query
|
|
base_query = cls.objects
|
|
if park:
|
|
base_query = base_query.filter(park=park)
|
|
|
|
try:
|
|
ride = base_query.get(slug=slug)
|
|
return ride, False
|
|
except cls.DoesNotExist:
|
|
# Try historical slugs in HistoricalSlug model
|
|
content_type = ContentType.objects.get_for_model(cls)
|
|
historical_query = HistoricalSlug.objects.filter(
|
|
content_type=content_type, slug=slug
|
|
).order_by("-created_at")
|
|
|
|
for historical in historical_query:
|
|
try:
|
|
ride = base_query.get(pk=historical.object_id)
|
|
return ride, True
|
|
except cls.DoesNotExist:
|
|
continue
|
|
|
|
# Try pghistory events
|
|
event_model = getattr(cls, "event_model", None)
|
|
if event_model:
|
|
historical_events = event_model.objects.filter(slug=slug).order_by("-pgh_created_at")
|
|
|
|
for historical_event in historical_events:
|
|
try:
|
|
ride = base_query.get(pk=historical_event.pgh_obj_id)
|
|
return ride, True
|
|
except cls.DoesNotExist:
|
|
continue
|
|
|
|
raise cls.DoesNotExist("No ride found with this slug")
|
|
```
|
|
|
|
### 2. Method Features
|
|
|
|
The implemented method provides:
|
|
|
|
- **Current slug lookup**: First attempts to find the ride by its current slug
|
|
- **Historical slug support**: Falls back to checking historical slugs in the `HistoricalSlug` model
|
|
- **pghistory integration**: Also checks pghistory events for historical slug changes
|
|
- **Park filtering**: Optional park parameter to limit search to rides within a specific park
|
|
- **Return tuple**: Returns `(ride_instance, is_historical)` where `is_historical` indicates if the slug was found in historical records
|
|
|
|
### 3. Pattern Consistency
|
|
|
|
This implementation follows the same pattern as the existing `Park.get_by_slug()` method, ensuring consistency across the codebase.
|
|
|
|
## Testing Results
|
|
|
|
### Before Fix
|
|
```bash
|
|
curl -n "http://localhost:8000/api/v1/parks/busch-gardens-tampa/rides/valkyrie/"
|
|
```
|
|
**Result:** AttributeError
|
|
|
|
### After Fix
|
|
```bash
|
|
curl -n "http://localhost:8000/api/v1/parks/busch-gardens-tampa/rides/valkyrie/"
|
|
```
|
|
**Result:** ✅ Success - Returns complete ride data:
|
|
```json
|
|
{
|
|
"id": 613,
|
|
"name": "Valkyrie",
|
|
"slug": "valkyrie",
|
|
"category": "FR",
|
|
"status": "OPERATING",
|
|
"description": "Exciting FR ride with thrilling elements and smooth operation",
|
|
"park": {
|
|
"id": 252,
|
|
"name": "Busch Gardens Tampa",
|
|
"slug": "busch-gardens-tampa",
|
|
"url": "http://www.thrillwiki.com/parks/busch-gardens-tampa/"
|
|
},
|
|
"park_area": {
|
|
"id": 794,
|
|
"name": "Fantasyland",
|
|
"slug": "fantasyland"
|
|
},
|
|
// ... additional ride data
|
|
}
|
|
```
|
|
|
|
## Impact
|
|
|
|
### Fixed Endpoints
|
|
- ✅ `GET /api/v1/parks/{park_slug}/rides/{ride_slug}/` - Now working correctly
|
|
- ✅ All park ride detail API calls now function properly
|
|
|
|
### Benefits
|
|
1. **API Reliability**: Park ride detail endpoints now work as expected
|
|
2. **Historical Slug Support**: Rides can be found even if their slugs have changed
|
|
3. **Consistent Patterns**: Matches the established pattern used by Park model
|
|
4. **Future-Proof**: Supports both current and historical slug lookups
|
|
|
|
## Files Modified
|
|
|
|
1. **backend/apps/rides/models/rides.py**
|
|
- Added `get_by_slug` class method to `Ride` model
|
|
- Implemented historical slug lookup functionality
|
|
- Added proper type hints and documentation
|
|
|
|
## Related Documentation
|
|
|
|
- [Park Detail Endpoint Documentation](./park-detail-endpoint-documentation.md)
|
|
- [Rich Choice Objects API Guide](./rich-choice-objects-api-guide.md)
|
|
- [Frontend Integration Guide](./frontend.md)
|
|
|
|
## Confidence Level
|
|
|
|
**10/10** - The issue was clearly identified, the solution follows established patterns, and testing confirms the fix works correctly.
|