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

@@ -0,0 +1,243 @@
"""
Tests for query optimization patterns in the parks app.
These tests verify that:
1. Manager methods use proper select_related/prefetch_related
2. Views don't trigger N+1 queries
3. Computed fields are updated correctly
"""
from django.test import TestCase
from django.db import connection
from django.test.utils import CaptureQueriesContext
from apps.parks.models import Park, ParkLocation, Company
class ParkQueryOptimizationTests(TestCase):
"""Tests for Park query optimization."""
@classmethod
def setUpTestData(cls):
"""Set up test data for all tests."""
# Create a test operator company
cls.operator = Company.objects.create(
name="Test Operator",
slug="test-operator",
roles=["OPERATOR"],
)
# Create test parks
cls.parks = []
for i in range(5):
park = Park.objects.create(
name=f"Test Park {i}",
slug=f"test-park-{i}",
operator=cls.operator,
timezone="UTC",
)
# Create location for each park
ParkLocation.objects.create(
park=park,
city=f"City {i}",
state="CA",
country="USA",
)
cls.parks.append(park)
def test_optimized_for_list_query_count(self):
"""Verify optimized_for_list uses expected number of queries."""
with CaptureQueriesContext(connection) as context:
parks = Park.objects.optimized_for_list()
# Force evaluation
list(parks)
# Should be a small number of queries (main query + prefetch)
# The exact count depends on prefetch_related configuration
self.assertLessEqual(
len(context.captured_queries),
5,
f"Expected <= 5 queries, got {len(context.captured_queries)}"
)
def test_optimized_for_detail_query_count(self):
"""Verify optimized_for_detail uses expected number of queries."""
with CaptureQueriesContext(connection) as context:
parks = Park.objects.optimized_for_detail()
park = parks.first()
if park:
# Access related objects that should be prefetched
_ = park.operator
_ = list(park.areas.all())
# Should be a reasonable number of queries
self.assertLessEqual(
len(context.captured_queries),
10,
f"Expected <= 10 queries, got {len(context.captured_queries)}"
)
def test_with_location_includes_location(self):
"""Verify with_location prefetches location data."""
with CaptureQueriesContext(connection) as context:
parks = Park.objects.with_location()
for park in parks:
# Accessing location should not cause additional queries
_ = park.location
# Should be minimal queries
self.assertLessEqual(len(context.captured_queries), 3)
def test_for_map_display_returns_minimal_fields(self):
"""Verify for_map_display returns only necessary fields."""
result = Park.objects.for_map_display()
if result.exists():
first = result.first()
# Should include these fields
self.assertIn('id', first)
self.assertIn('name', first)
self.assertIn('slug', first)
self.assertIn('status', first)
def test_search_autocomplete_limits_results(self):
"""Verify search_autocomplete respects limit parameter."""
result = Park.objects.search_autocomplete(query="Test", limit=3)
self.assertLessEqual(len(result), 3)
class CompanyQueryOptimizationTests(TestCase):
"""Tests for Company query optimization."""
@classmethod
def setUpTestData(cls):
"""Set up test data for all tests."""
# Create test companies with different roles
cls.manufacturers = []
for i in range(5):
company = Company.objects.create(
name=f"Manufacturer {i}",
slug=f"manufacturer-{i}",
roles=["MANUFACTURER"],
)
cls.manufacturers.append(company)
cls.operators = []
for i in range(3):
company = Company.objects.create(
name=f"Operator {i}",
slug=f"operator-{i}",
roles=["OPERATOR"],
)
cls.operators.append(company)
def test_manufacturers_query_only_returns_manufacturers(self):
"""Verify manufacturers() only returns companies with MANUFACTURER role."""
result = Company.objects.manufacturers()
for company in result:
self.assertIn("MANUFACTURER", company.roles)
def test_operators_query_only_returns_operators(self):
"""Verify operators() only returns companies with OPERATOR role."""
result = Company.objects.operators()
for company in result:
self.assertIn("OPERATOR", company.roles)
def test_manufacturers_with_ride_count_includes_annotation(self):
"""Verify manufacturers_with_ride_count adds ride_count annotation."""
result = Company.objects.manufacturers_with_ride_count()
if result.exists():
first = result.first()
# Should have ride_count attribute
self.assertTrue(hasattr(first, 'ride_count'))
def test_operators_with_park_count_includes_annotation(self):
"""Verify operators_with_park_count adds park count annotations."""
result = Company.objects.operators_with_park_count()
if result.exists():
first = result.first()
# Should have operated_parks_count attribute
self.assertTrue(hasattr(first, 'operated_parks_count'))
class ComputedFieldMaintenanceTests(TestCase):
"""Tests for computed field maintenance via signals."""
@classmethod
def setUpTestData(cls):
"""Set up test data for all tests."""
cls.operator = Company.objects.create(
name="Test Operator",
slug="test-operator",
roles=["OPERATOR"],
)
def test_park_search_text_includes_name(self):
"""Verify park search_text includes park name."""
park = Park.objects.create(
name="Magic Kingdom",
slug="magic-kingdom",
operator=self.operator,
timezone="UTC",
)
self.assertIn("magic kingdom", park.search_text.lower())
def test_park_search_text_includes_description(self):
"""Verify park search_text includes description."""
park = Park.objects.create(
name="Test Park",
slug="test-park",
description="A magical theme park experience",
operator=self.operator,
timezone="UTC",
)
self.assertIn("magical", park.search_text.lower())
def test_park_search_text_includes_operator(self):
"""Verify park search_text includes operator name."""
park = Park.objects.create(
name="Test Park",
slug="test-park-2",
operator=self.operator,
timezone="UTC",
)
self.assertIn("test operator", park.search_text.lower())
def test_park_opening_year_computed_from_date(self):
"""Verify opening_year is computed from opening_date."""
from datetime import date
park = Park.objects.create(
name="Test Park",
slug="test-park-3",
operator=self.operator,
timezone="UTC",
opening_date=date(1971, 10, 1),
)
self.assertEqual(park.opening_year, 1971)
def test_park_search_text_updated_on_location_change(self):
"""Verify park search_text updates when location changes."""
park = Park.objects.create(
name="Test Park",
slug="test-park-4",
operator=self.operator,
timezone="UTC",
)
# Initially no location in search_text
original_search_text = park.search_text
# Add location
location = ParkLocation.objects.create(
park=park,
city="Orlando",
state="Florida",
country="USA",
)
# Refresh park from database
park.refresh_from_db()
# Search text should now include location
# Note: This depends on signal handlers being properly registered
# The actual behavior may vary based on signal configuration