Add comprehensive API documentation for ThrillWiki integration and features

- 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.
This commit is contained in:
pacnpal
2025-09-16 11:29:17 -04:00
parent 61d73a2147
commit c2c26cfd1d
98 changed files with 11476 additions and 4803 deletions

View File

@@ -93,36 +93,28 @@ class SearchTextForm(BaseFilterForm):
class BasicInfoForm(BaseFilterForm):
"""Form for basic ride information filters."""
CATEGORY_CHOICES = [
("", "All Categories"),
("roller_coaster", "Roller Coaster"),
("water_ride", "Water Ride"),
("flat_ride", "Flat Ride"),
("dark_ride", "Dark Ride"),
("kiddie_ride", "Kiddie Ride"),
("transport", "Transport"),
("show", "Show"),
("other", "Other"),
]
STATUS_CHOICES = [
("", "All Statuses"),
("operating", "Operating"),
("closed_temporary", "Temporarily Closed"),
("closed_permanent", "Permanently Closed"),
("under_construction", "Under Construction"),
("announced", "Announced"),
("rumored", "Rumored"),
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Get choices from Rich Choice registry
from apps.core.choices.registry import get_choices
# Get choices - let exceptions propagate if registry fails
category_choices = [(choice.value, choice.label) for choice in get_choices("categories", "rides")]
status_choices = [(choice.value, choice.label) for choice in get_choices("statuses", "rides")]
# Update field choices dynamically
self.fields['category'].choices = category_choices
self.fields['status'].choices = status_choices
category = forms.MultipleChoiceField(
choices=CATEGORY_CHOICES[1:], # Exclude "All Categories"
choices=[], # Will be populated in __init__
required=False,
widget=forms.CheckboxSelectMultiple(attrs={"class": "grid grid-cols-2 gap-2"}),
)
status = forms.MultipleChoiceField(
choices=STATUS_CHOICES[1:], # Exclude "All Statuses"
choices=[], # Will be populated in __init__
required=False,
widget=forms.CheckboxSelectMultiple(attrs={"class": "space-y-2"}),
)
@@ -346,35 +338,21 @@ class RelationshipsForm(BaseFilterForm):
class RollerCoasterForm(BaseFilterForm):
"""Form for roller coaster specific filters."""
TRACK_MATERIAL_CHOICES = [
("steel", "Steel"),
("wood", "Wood"),
("hybrid", "Hybrid"),
]
COASTER_TYPE_CHOICES = [
("sit_down", "Sit Down"),
("inverted", "Inverted"),
("floorless", "Floorless"),
("flying", "Flying"),
("suspended", "Suspended"),
("stand_up", "Stand Up"),
("spinning", "Spinning"),
("launched", "Launched"),
("hypercoaster", "Hypercoaster"),
("giga_coaster", "Giga Coaster"),
("strata_coaster", "Strata Coaster"),
]
LAUNCH_TYPE_CHOICES = [
("none", "No Launch"),
("lim", "LIM (Linear Induction Motor)"),
("lsm", "LSM (Linear Synchronous Motor)"),
("hydraulic", "Hydraulic"),
("pneumatic", "Pneumatic"),
("cable", "Cable"),
("flywheel", "Flywheel"),
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Get choices from Rich Choice registry
from apps.core.choices.registry import get_choices
# Get choices - let exceptions propagate if registry fails
track_material_choices = [(choice.value, choice.label) for choice in get_choices("track_materials", "rides")]
coaster_type_choices = [(choice.value, choice.label) for choice in get_choices("coaster_types", "rides")]
launch_type_choices = [(choice.value, choice.label) for choice in get_choices("launch_systems", "rides")]
# Update field choices dynamically
self.fields['track_material'].choices = track_material_choices
self.fields['coaster_type'].choices = coaster_type_choices
self.fields['launch_type'].choices = launch_type_choices
height_ft_range = NumberRangeField(
min_val=0, max_val=500, step=1, required=False, label="Height (feet)"
@@ -393,13 +371,13 @@ class RollerCoasterForm(BaseFilterForm):
)
track_material = forms.MultipleChoiceField(
choices=TRACK_MATERIAL_CHOICES,
choices=[], # Will be populated in __init__
required=False,
widget=forms.CheckboxSelectMultiple(attrs={"class": "space-y-2"}),
)
coaster_type = forms.MultipleChoiceField(
choices=COASTER_TYPE_CHOICES,
choices=[], # Will be populated in __init__
required=False,
widget=forms.CheckboxSelectMultiple(
attrs={"class": "grid grid-cols-2 gap-2 max-h-48 overflow-y-auto"}
@@ -407,7 +385,7 @@ class RollerCoasterForm(BaseFilterForm):
)
launch_type = forms.MultipleChoiceField(
choices=LAUNCH_TYPE_CHOICES,
choices=[], # Will be populated in __init__
required=False,
widget=forms.CheckboxSelectMultiple(
attrs={"class": "space-y-2 max-h-48 overflow-y-auto"}
@@ -418,20 +396,29 @@ class RollerCoasterForm(BaseFilterForm):
class CompanyForm(BaseFilterForm):
"""Form for company-related filters."""
ROLE_CHOICES = [
("MANUFACTURER", "Manufacturer"),
("DESIGNER", "Designer"),
("OPERATOR", "Operator"),
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Get choices from Rich Choice registry
from apps.core.choices.registry import get_choices
# Get both rides and parks company roles - let exceptions propagate if registry fails
rides_roles = [(choice.value, choice.label) for choice in get_choices("company_roles", "rides")]
parks_roles = [(choice.value, choice.label) for choice in get_choices("company_roles", "parks")]
role_choices = rides_roles + parks_roles
# Update field choices dynamically
self.fields['manufacturer_roles'].choices = role_choices
self.fields['designer_roles'].choices = role_choices
manufacturer_roles = forms.MultipleChoiceField(
choices=ROLE_CHOICES,
choices=[], # Will be populated in __init__
required=False,
widget=forms.CheckboxSelectMultiple(attrs={"class": "space-y-2"}),
)
designer_roles = forms.MultipleChoiceField(
choices=ROLE_CHOICES,
choices=[], # Will be populated in __init__
required=False,
widget=forms.CheckboxSelectMultiple(attrs={"class": "space-y-2"}),
)
@@ -444,24 +431,31 @@ class CompanyForm(BaseFilterForm):
class SortingForm(BaseFilterForm):
"""Form for sorting options."""
SORT_CHOICES = [
("relevance", "Relevance"),
("name_asc", "Name (A-Z)"),
("name_desc", "Name (Z-A)"),
("opening_date_asc", "Opening Date (Oldest)"),
("opening_date_desc", "Opening Date (Newest)"),
("rating_asc", "Rating (Lowest)"),
("rating_desc", "Rating (Highest)"),
("height_asc", "Height (Shortest)"),
("height_desc", "Height (Tallest)"),
("speed_asc", "Speed (Slowest)"),
("speed_desc", "Speed (Fastest)"),
("capacity_asc", "Capacity (Lowest)"),
("capacity_desc", "Capacity (Highest)"),
]
# Static sorting choices - these are UI-specific and don't need Rich Choice Objects
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Static sort choices for UI functionality
sort_choices = [
("relevance", "Relevance"),
("name_asc", "Name (A-Z)"),
("name_desc", "Name (Z-A)"),
("opening_date_asc", "Opening Date (Oldest)"),
("opening_date_desc", "Opening Date (Newest)"),
("rating_asc", "Rating (Lowest)"),
("rating_desc", "Rating (Highest)"),
("height_asc", "Height (Shortest)"),
("height_desc", "Height (Tallest)"),
("speed_asc", "Speed (Slowest)"),
("speed_desc", "Speed (Fastest)"),
("capacity_asc", "Capacity (Lowest)"),
("capacity_desc", "Capacity (Highest)"),
]
self.fields['sort_by'].choices = sort_choices
sort_by = forms.ChoiceField(
choices=SORT_CHOICES,
choices=[], # Will be populated in __init__
required=False,
initial="relevance",
widget=forms.Select(