feat: Refactor rides app with unique constraints, mixins, and enhanced documentation

- Added migration to convert unique_together constraints to UniqueConstraint for RideModel.
- Introduced RideFormMixin for handling entity suggestions in ride forms.
- Created comprehensive code standards documentation outlining formatting, docstring requirements, complexity guidelines, and testing requirements.
- Established error handling guidelines with a structured exception hierarchy and best practices for API and view error handling.
- Documented view pattern guidelines, emphasizing the use of CBVs, FBVs, and ViewSets with examples.
- Implemented a benchmarking script for query performance analysis and optimization.
- Developed security documentation detailing measures, configurations, and a security checklist.
- Compiled a database optimization guide covering indexing strategies, query optimization patterns, and computed fields.
This commit is contained in:
pacnpal
2025-12-22 11:17:31 -05:00
parent 45d97b6e68
commit 2e35f8c5d9
71 changed files with 8036 additions and 1462 deletions

View File

@@ -11,6 +11,28 @@ from .models import Park
logger = logging.getLogger(__name__)
# =============================================================================
# Computed Field Maintenance Signals
# =============================================================================
def update_park_search_text(park):
"""
Update park's search_text computed field.
This is called when related objects (location, operator, property_owner)
change and might affect the park's search text.
"""
if park is None:
return
try:
park._populate_computed_fields()
park.save(update_fields=['search_text'])
logger.debug(f"Updated search_text for park {park.pk}")
except Exception as e:
logger.exception(f"Failed to update search_text for park {park.pk}: {e}")
# Status values that count as "active" rides for counting purposes
ACTIVE_STATUSES = {'OPERATING', 'SEASONAL', 'UNDER_CONSTRUCTION'}
@@ -46,8 +68,8 @@ def update_park_ride_counts(park, old_status=None, new_status=None):
# Count total operating rides
ride_count = park.rides.filter(operating_rides).count()
# Count total operating roller coasters
coaster_count = park.rides.filter(operating_rides, category="RC").count()
# Count total operating roller coasters (including water coasters)
coaster_count = park.rides.filter(operating_rides, category__in=["RC", "WC"]).count()
# Update park counts
Park.objects.filter(id=park_id).update(
@@ -148,3 +170,44 @@ def handle_ride_status_transition(instance, source, target, user, **kwargs):
f"by {user if user else 'system'}"
)
update_park_ride_counts(instance.park, source, target)
# =============================================================================
# Computed Field Maintenance Signal Handlers
# =============================================================================
@receiver(post_save, sender='parks.ParkLocation')
def update_park_search_text_on_location_change(sender, instance, **kwargs):
"""
Update park search_text when location changes.
When a park's location is updated (city, state, country changes),
the park's search_text needs to be regenerated to include the new
location information.
"""
try:
if hasattr(instance, 'park') and instance.park:
update_park_search_text(instance.park)
except Exception as e:
logger.exception(f"Failed to update park search_text on location change: {e}")
@receiver(post_save, sender='parks.Company')
def update_park_search_text_on_company_change(sender, instance, **kwargs):
"""
Update park search_text when operator/owner name changes.
When a company's name changes, all parks operated or owned by that
company need their search_text regenerated.
"""
try:
# Update all parks operated by this company
for park in instance.operated_parks.all():
update_park_search_text(park)
# Update all parks owned by this company
for park in instance.owned_parks.all():
update_park_search_text(park)
except Exception as e:
logger.exception(f"Failed to update park search_text on company change: {e}")